From ce65c55d338e8be2249e92b2fd7a6377a1b46a79 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Sat, 1 Feb 2025 19:41:29 -0500 Subject: [PATCH 01/18] init auto fix --- .../frontend-code-generate/CodeTaskQueue.ts | 20 ++ .../FrontendCodeValidator.ts | 123 ++++++++++++ .../FrontendQueueProcessor.ts | 185 ++++++++++++++++++ .../handlers/frontend-code-generate/index.ts | 41 ++-- 4 files changed, 358 insertions(+), 11 deletions(-) create mode 100644 backend/src/build-system/handlers/frontend-code-generate/CodeTaskQueue.ts create mode 100644 backend/src/build-system/handlers/frontend-code-generate/FrontendCodeValidator.ts create mode 100644 backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts diff --git a/backend/src/build-system/handlers/frontend-code-generate/CodeTaskQueue.ts b/backend/src/build-system/handlers/frontend-code-generate/CodeTaskQueue.ts new file mode 100644 index 00000000..56266656 --- /dev/null +++ b/backend/src/build-system/handlers/frontend-code-generate/CodeTaskQueue.ts @@ -0,0 +1,20 @@ +export interface FileTask { + filePath: string; // e.g. "src/components/MyComponent.ts" + fileContents: string; // the code you got from the LLM +} + +export class CodeTaskQueue { + private tasks: FileTask[] = []; + + enqueue(task: FileTask) { + this.tasks.push(task); + } + + dequeue(): FileTask | undefined { + return this.tasks.shift(); + } + + get size(): number { + return this.tasks.length; + } +} diff --git a/backend/src/build-system/handlers/frontend-code-generate/FrontendCodeValidator.ts b/backend/src/build-system/handlers/frontend-code-generate/FrontendCodeValidator.ts new file mode 100644 index 00000000..cb6c4f24 --- /dev/null +++ b/backend/src/build-system/handlers/frontend-code-generate/FrontendCodeValidator.ts @@ -0,0 +1,123 @@ +import { spawn } from 'child_process'; +import { Logger } from '@nestjs/common'; + +export interface ValidationResult { + success: boolean; + error?: string; +} + +/** + * FrontendCodeValidator is responsible for checking the correctness of the generated frontend code. + * It runs an npm build command (or any custom build script) in the given project directory (frontendPath) + * and captures any errors produced during the build process. + */ +export class FrontendCodeValidator { + private readonly logger = new Logger('FrontendCodeValidator'); + + /** + * @param frontendPath - The absolute path to the generated frontend project. + */ + constructor(private readonly frontendPath: string) {} + + /** + * Runs the build command (npm run build) inside the frontend project directory. + * This method returns a promise that resolves with a ValidationResult, indicating whether + * the build succeeded or failed along with any error messages. + * + * @returns A promise that resolves with the ValidationResult. + */ + public async validate(): Promise { + return new Promise((resolve, reject) => { + this.logger.log('Starting frontend code validation...'); + // Spawn the npm build process in the provided frontend project path. + const npmProcess = spawn('npm', ['run', 'build'], { + cwd: this.frontendPath, + shell: true, + }); + + this.logger.log('Running npm build command in', this.frontendPath); + let stdoutBuffer = ''; + let stderrBuffer = ''; + + npmProcess.stdout.on('data', (data: Buffer) => { + const output = data.toString(); + stdoutBuffer += output; + // this.logger.log(output); + }); + + npmProcess.stderr.on('data', (data: Buffer) => { + const output = data.toString(); + stderrBuffer += output; + // this.logger.log(output); + }); + + npmProcess.on('close', (code: number) => { + if (code !== 0) { + // Build failed – use stderr if available, else fallback to stdout. + const errorMessage = stderrBuffer || stdoutBuffer; + // this.logger.error( + // `Build process exited with code ${code}. Error: ${errorMessage}`, + // ); + + this.logger.error(`Build process exited with code 0.`); + // this.logger.error(`Build process exited with code ${code}.`); + resolve({ + success: false, + error: errorMessage, + }); + } else { + // Build succeeded + this.logger.log('Build process completed successfully.'); + resolve({ + success: true, + }); + } + }); + + npmProcess.on('error', (err: Error) => { + this.logger.error('Failed to run npm build command:', err); + reject(err); + }); + }); + } + + public async installDependencies(): Promise { + return new Promise((resolve, reject) => { + this.logger.log('Starting npm install in', this.frontendPath); + + const npmInstall = spawn('npm', ['install'], { + cwd: this.frontendPath, + }); + + let stdoutBuffer = ''; + let stderrBuffer = ''; + + npmInstall.stdout.on('data', (data: Buffer) => { + stdoutBuffer += data.toString(); + }); + + npmInstall.stderr.on('data', (data: Buffer) => { + stderrBuffer += data.toString(); + }); + + npmInstall.on('close', (code: number) => { + if (code !== 0) { + const errorMessage = stderrBuffer || stdoutBuffer; + this.logger.error(`npm install exited with code ${code}.`); + resolve({ + success: false, + error: errorMessage, + }); + } else { + this.logger.log('npm install completed successfully.'); + resolve({ success: true }); + } + }); + + npmInstall.on('error', (err: Error) => { + this.logger.error('Failed to run npm install command:', err); + reject(err); + }); + }); + } +} diff --git a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts new file mode 100644 index 00000000..cebb1275 --- /dev/null +++ b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts @@ -0,0 +1,185 @@ +import { Logger } from '@nestjs/common'; +import { FrontendCodeValidator } from './FrontendCodeValidator'; +import { CodeTaskQueue, FileTask } from './CodeTaskQueue'; +import { readFileSync, writeFileSync } from 'fs'; +import { chatSyncWithClocker } from 'src/build-system/utils/handler-helper'; +import { createFileWithRetries } from 'src/build-system/utils/files'; +import { BuilderContext } from 'src/build-system/context'; + +export class FrontendQueueProcessor { + private logger = new Logger('FrontendQueueProcessor'); + + constructor( + private validator: FrontendCodeValidator, // Path to your frontend project + private queue: CodeTaskQueue, + private context: BuilderContext, // The queue of files to process + ) {} + + /** + * Process the entire queue, one file at a time. + */ + public async processAllTasks(): Promise { + while (this.queue.size > 0) { + const task = this.queue.dequeue(); + if (!task) break; + + await this.processSingleTask(task); + + this.logger.log(`Remaining tasks in queue: ${this.queue.size}`); + } + + this.logger.log('All tasks processed successfully!'); + } + + /** + * For a single file: + * 1. Write it to disk + * 2. Run "npm run build" (through the validator) + * 3. If error -> try to fix -> repeat until success or max attempts. + */ + private async processSingleTask(task: FileTask): Promise { + this.logger.log(`Processing file task: ${task.filePath}`); + + // 1. Write the file to disk + createFileWithRetries(task.filePath, task.fileContents); + + const maxFixAttempts = 3; + + for (let attempt = 1; attempt <= maxFixAttempts; attempt++) { + const validationResult = await this.validator.validate(); + + if (validationResult.success) { + this.logger.log( + `File ${task.filePath} build succeeded on attempt #${attempt}.`, + ); + return; // done, move on + } + + // Build failed. We'll feed the entire `validationResult.error` back to GPT + // this.logger.warn( + // `Build failed on attempt #${attempt} for file ${task.filePath}. Error:\n${validationResult.error}`, + // ); + + this.logger.warn( + `Build failed on attempt #${attempt} for file ${task.filePath}.`, + ); + + // 3. Fix the file + await this.fixFileGeneric(task.filePath, validationResult.error ?? ''); + + // Now we loop back, re-run the build to see if it's fixed. + } + + // If we reached here, we failed all attempts + // throw new Error( + // `Failed to fix build for file ${task.filePath} after ${maxFixAttempts} attempts.`, + // ); + + // if we dont want to end the process + this.logger.error( + `Failed to fix build for file ${task.filePath} after ${maxFixAttempts} attempts.`, + ); + } + + /** + * Attempt to fix a known file error using an LLM prompt that includes: + * - The existing code + * - The compiler error info + */ + private async fixFileError(filePath: string, errDetail: any) { + this.logger.log(`Fixing error in file: ${filePath}`); + const originalContent = readFileSync(filePath, 'utf-8'); + + // Construct your "fix" prompt + const fixPrompt = ` +There's a TypeScript error in file: ${filePath} +Line: ${errDetail.line}, Column: ${errDetail.column} +Error code: ${errDetail.tsCode} +Message: ${errDetail.message} + +Current file content: +\`\`\` +${originalContent} +\`\`\` + +Please fix the code so that this error is resolved. Return only the updated code wrapped in tags. +`; + + // Use your chat function to get a fix + const fixResponse = await chatSyncWithClocker( + /* context= */ null, // or pass your real context + { + model: 'gpt-4', + messages: [ + { role: 'system', content: 'You fix TypeScript code errors.' }, + { role: 'user', content: fixPrompt }, + ], + }, + 'fix code', + 'FrontendQueueProcessor', + ); + + // Extract the code + const updatedCode = this.extractGenerateContent(fixResponse); + + // Overwrite file + writeFileSync(filePath, updatedCode, 'utf-8'); + this.logger.log(`File ${filePath} has been updated to address the error.`); + } + + /** + * Fallback if you have no structured error details. + */ + private async fixFileGeneric(filePath: string, rawErrorText: string) { + this.logger.log(`Generic fix attempt for file: ${filePath}`); + const originalContent = readFileSync(filePath, 'utf-8'); + + const fixPrompt = ` +We have a TypeScript build failure. The raw error text is: +\`\`\` +${rawErrorText} +\`\`\` + +The file content is: +\`\`\` +${originalContent} +\`\`\` + +Please fix the code so it compiles successfully. Return only the updated code wrapped in tags. +`; + + // Use your model for a fix + const fixResponse = await chatSyncWithClocker( + /* context= */ this.context, + { + model: 'gpt-4o', + messages: [ + { role: 'system', content: 'You fix TypeScript code errors.' }, + { role: 'user', content: fixPrompt }, + ], + }, + 'fix code (generic)', + 'FrontendQueueProcessor', + ); + + this.logger.debug('Fix result' + fixResponse); + const updatedCode = this.extractGenerateContent(fixResponse); + writeFileSync(filePath, updatedCode, 'utf-8'); + this.logger.log(`Generic fix applied to file: ${filePath}`); + } + + /** + * Example helper to parse out ... . + * Or you might have your existing formatResponse() logic. + */ + private extractGenerateContent(modelResponse: string): string { + // For example, a regex or a simple parse: + const regex = /([\s\S]*?)<\/GENERATE>/; + const match = modelResponse.match(regex); + if (match && match[1]) { + return match[1].trim(); + } + // If not found, fallback to the entire response + return modelResponse; + } +} diff --git a/backend/src/build-system/handlers/frontend-code-generate/index.ts b/backend/src/build-system/handlers/frontend-code-generate/index.ts index 6cd92d10..b678e2fe 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/index.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/index.ts @@ -3,7 +3,7 @@ import { BuilderContext } from 'src/build-system/context'; import { Logger } from '@nestjs/common'; import { chatSyncWithClocker } from 'src/build-system/utils/handler-helper'; import { generateFilesDependencyWithLayers } from '../../utils/file_generator_util'; -import { readFileWithRetries, createFileWithRetries } from '../../utils/files'; +import { readFileWithRetries } from '../../utils/files'; import { VirtualDirectory } from '../../virtual-dir'; import { UXSMSHandler } from '../ux/sitemap-structure'; @@ -18,6 +18,9 @@ import { formatResponse } from 'src/build-system/utils/strings'; import { writeFileSync } from 'fs'; import { MessageInterface } from 'src/common/model-provider/types'; +import { CodeTaskQueue } from './CodeTaskQueue'; +import { FrontendQueueProcessor } from './FrontendQueueProcessor'; +import { FrontendCodeValidator } from './FrontendCodeValidator'; /** * FrontendCodeHandler is responsible for generating the frontend codebase * based on the provided sitemap, data mapping documents, backend requirement documents, @@ -79,6 +82,9 @@ export class FrontendCodeHandler implements BuildHandler { const { concurrencyLayers, fileInfos } = await generateFilesDependencyWithLayers(fileArchDoc, this.virtualDir); + const validator = new FrontendCodeValidator(frontendPath); + // validator.installDependencies(); + // 4. Process each "layer" in sequence; files in a layer in parallel for (const [layerIndex, layer] of concurrencyLayers.entries()) { this.logger.log( @@ -87,6 +93,8 @@ export class FrontendCodeHandler implements BuildHandler { )}]\n`, ); + const queue = new CodeTaskQueue(); + const maxRetries = 3; // Maximum retry attempts per file const delayMs = 200; // Delay between retries for a file let remainingFiles = [...layer]; // Start with all files in the layer @@ -215,13 +223,19 @@ export class FrontendCodeHandler implements BuildHandler { generatedCode = formatResponse(modelResponse); + // 7. Add the file to the queue for writing + queue.enqueue({ + filePath: currentFullFilePath, // relative path + fileContents: generatedCode, + }); + // 7. Write the file to the filesystem - await createFileWithRetries( - currentFullFilePath, - generatedCode, - maxRetries, - delayMs, - ); + // await createFileWithRetries( + // currentFullFilePath, + // generatedCode, + // maxRetries, + // delayMs, + // ); } catch (err) { this.logger.error(`Error generating code for ${file}:`, err); // FIXME: remove this later @@ -235,10 +249,6 @@ export class FrontendCodeHandler implements BuildHandler { }), ); } - - this.logger.log( - `Layer #${layerIndex + 1}, completed generation for file: ${file}`, - ); }), ); @@ -259,6 +269,15 @@ export class FrontendCodeHandler implements BuildHandler { } } + // B) Now process the entire queue for this layer: + // This writes each file, runs build, fixes if needed, etc. + const queueProcessor = new FrontendQueueProcessor( + validator, + queue, + context, + ); + await queueProcessor.processAllTasks(); + this.logger.log( `\n==== Finished concurrency layer #${layerIndex + 1} ====\n`, ); From 61c103c2b763a23a74908fc60656eb3d5dda0e16 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Sun, 2 Feb 2025 17:06:56 -0500 Subject: [PATCH 02/18] delete unused function --- .../FrontendQueueProcessor.ts | 74 +++---------------- 1 file changed, 9 insertions(+), 65 deletions(-) diff --git a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts index cebb1275..49543cb1 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts @@ -5,6 +5,7 @@ import { readFileSync, writeFileSync } from 'fs'; import { chatSyncWithClocker } from 'src/build-system/utils/handler-helper'; import { createFileWithRetries } from 'src/build-system/utils/files'; import { BuilderContext } from 'src/build-system/context'; +import { formatResponse } from 'src/build-system/utils/strings'; export class FrontendQueueProcessor { private logger = new Logger('FrontendQueueProcessor'); @@ -71,6 +72,8 @@ export class FrontendQueueProcessor { } // If we reached here, we failed all attempts + + // if we want to end all generate // throw new Error( // `Failed to fix build for file ${task.filePath} after ${maxFixAttempts} attempts.`, // ); @@ -81,52 +84,6 @@ export class FrontendQueueProcessor { ); } - /** - * Attempt to fix a known file error using an LLM prompt that includes: - * - The existing code - * - The compiler error info - */ - private async fixFileError(filePath: string, errDetail: any) { - this.logger.log(`Fixing error in file: ${filePath}`); - const originalContent = readFileSync(filePath, 'utf-8'); - - // Construct your "fix" prompt - const fixPrompt = ` -There's a TypeScript error in file: ${filePath} -Line: ${errDetail.line}, Column: ${errDetail.column} -Error code: ${errDetail.tsCode} -Message: ${errDetail.message} - -Current file content: -\`\`\` -${originalContent} -\`\`\` - -Please fix the code so that this error is resolved. Return only the updated code wrapped in tags. -`; - - // Use your chat function to get a fix - const fixResponse = await chatSyncWithClocker( - /* context= */ null, // or pass your real context - { - model: 'gpt-4', - messages: [ - { role: 'system', content: 'You fix TypeScript code errors.' }, - { role: 'user', content: fixPrompt }, - ], - }, - 'fix code', - 'FrontendQueueProcessor', - ); - - // Extract the code - const updatedCode = this.extractGenerateContent(fixResponse); - - // Overwrite file - writeFileSync(filePath, updatedCode, 'utf-8'); - this.logger.log(`File ${filePath} has been updated to address the error.`); - } - /** * Fallback if you have no structured error details. */ @@ -148,9 +105,11 @@ ${originalContent} Please fix the code so it compiles successfully. Return only the updated code wrapped in tags. `; - // Use your model for a fix + //this.logger.log(fixPrompt); + + // Use model for a fix const fixResponse = await chatSyncWithClocker( - /* context= */ this.context, + this.context, { model: 'gpt-4o', messages: [ @@ -162,24 +121,9 @@ Please fix the code so it compiles successfully. Return only the updated code wr 'FrontendQueueProcessor', ); - this.logger.debug('Fix result' + fixResponse); - const updatedCode = this.extractGenerateContent(fixResponse); + // this.logger.debug('Fix result' + fixResponse); + const updatedCode = formatResponse(fixResponse); writeFileSync(filePath, updatedCode, 'utf-8'); this.logger.log(`Generic fix applied to file: ${filePath}`); } - - /** - * Example helper to parse out ... . - * Or you might have your existing formatResponse() logic. - */ - private extractGenerateContent(modelResponse: string): string { - // For example, a regex or a simple parse: - const regex = /([\s\S]*?)<\/GENERATE>/; - const match = modelResponse.match(regex); - if (match && match[1]) { - return match[1].trim(); - } - // If not found, fallback to the entire response - return modelResponse; - } } From 183d960a655bb1112859538fc8ea879e47c7a7d2 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Mon, 3 Feb 2025 21:56:13 -0500 Subject: [PATCH 03/18] init llm operation --- .../frontend-code-generate/CodeTaskQueue.ts | 1 + .../FileOperationManager.ts | 107 ++++++++++++++ .../FixResponseParser.ts | 103 ++++++++++++++ .../FrontendCodeValidator.ts | 3 +- .../FrontendQueueProcessor.ts | 78 +++++++--- .../handlers/frontend-code-generate/index.ts | 10 +- .../handlers/frontend-code-generate/prompt.ts | 133 ++++++++++++++++++ 7 files changed, 407 insertions(+), 28 deletions(-) create mode 100644 backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts create mode 100644 backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts diff --git a/backend/src/build-system/handlers/frontend-code-generate/CodeTaskQueue.ts b/backend/src/build-system/handlers/frontend-code-generate/CodeTaskQueue.ts index 56266656..1b6e6ad5 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/CodeTaskQueue.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/CodeTaskQueue.ts @@ -1,6 +1,7 @@ export interface FileTask { filePath: string; // e.g. "src/components/MyComponent.ts" fileContents: string; // the code you got from the LLM + dependenciesPath?: string; } export class CodeTaskQueue { diff --git a/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts new file mode 100644 index 00000000..240eff87 --- /dev/null +++ b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts @@ -0,0 +1,107 @@ +import { Logger } from '@nestjs/common'; +import { writeFile, rename } from 'fs/promises'; +import path from 'path'; + +export interface FileOperation { + action: 'read' | 'write' | 'delete' | 'rename'; + path: string; + originalPath: string; + content?: string; + purpose?: string; +} + +export interface LLMFixResponse { + operations: FileOperation[]; + reasoning: string; + code?: string; +} + +export class FileOperationManager { + private readonly projectRoot: string; + private readonly allowedPaths: string[]; + private logger = new Logger('FileOperationManager'); + + constructor(projectRoot: string) { + this.projectRoot = path.normalize(projectRoot); + this.allowedPaths = [this.projectRoot]; + } + + private operationCount = 0; + async executeOperations(operations: FileOperation[]): Promise { + // if (operations.length > 5) { + // throw new Error('Maximum 5 operations per fix'); + // } + + for (const op of operations) { + const resolvedPath = path.resolve(this.projectRoot, op.path); + + try { + switch (op.action) { + case 'write': + await this.handleWrite(resolvedPath, op); + break; + case 'rename': + await this.handleRename(resolvedPath, op); + break; + } + } catch (error) { + this.logger.error(`Failed to ${op.action} ${resolvedPath}: ${error}`); + throw error; + } + } + } + + private async handleWrite( + filePath: string, + op: FileOperation, + ): Promise { + this.safetyChecks(op); + await writeFile(filePath, op.content, 'utf-8'); + } + + private async handleRename( + filePath: string, + op: FileOperation, + ): Promise { + this.safetyChecks(op); + + // Perform the actual rename + await rename(op.originalPath, filePath); + } + + private safetyChecks(op: FileOperation) { + const targetPath = path.resolve(this.projectRoot, op.path); // Normalize path + + // Prevent path traversal attacks + if (!targetPath.startsWith(this.projectRoot)) { + throw new Error('Unauthorized file access detected'); + } + + // Prevent package.json modifications + if (op.path.includes('package.json')) { + throw new Error('Modifying package.json requires special approval'); + } + + // Security check + if (!this.isPathAllowed(targetPath)) { + throw new Error(`Attempted to access restricted path: ${targetPath}`); + } + + // Limit delete write operations + if ( + (op.action === 'delete' || op.action === 'write') && + !op.path.startsWith('src/') + ) { + throw new Error('Can only delete or write files in src/ directory'); + } + } + + private isPathAllowed(targetPath: string): boolean { + return this.allowedPaths.some( + (allowedPath) => + targetPath.startsWith(allowedPath) && + !targetPath.includes('node_modules') && + !targetPath.includes('.env'), + ); + } +} diff --git a/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts b/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts new file mode 100644 index 00000000..60b88440 --- /dev/null +++ b/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts @@ -0,0 +1,103 @@ +import { XMLParser } from 'fast-xml-parser'; +import { FileOperation, LLMFixResponse } from './FileOperationManager'; +import { Logger } from '@nestjs/common'; +import path from 'path'; + +export class FixResponseParser { + private readonly parser: XMLParser; + private readonly logger = new Logger('FixResponseParser'); + + constructor() { + this.parser = new XMLParser({ + ignoreAttributes: false, + attributeNamePrefix: '', + textNodeName: 'value', + allowBooleanAttributes: true, + alwaysCreateTextNode: true + }); + } + + parse(xml: string): LLMFixResponse { + try { + const parsed = this.parser.parse(xml); + return this.transformResponse(parsed); + } catch (error) { + this.logger.error('XML parsing failed', error.stack); + throw new Error('Invalid XML format from LLM'); + } + } + + private transformResponse(parsed: any): LLMFixResponse { + const result: LLMFixResponse = { + operations: [], + reasoning: '' + }; + + // Extract reasoning if available + result.reasoning = parsed.FIX.REASONING?.value || 'No reasoning provided'; + + // Process operations + const actions = parsed.FIX.OPERATIONS?.ACTION || []; + const actionsArray = Array.isArray(actions) ? actions : [actions]; + + for (const action of actionsArray) { + const operation = this.parseAction(action); + if (operation) result.operations.push(operation); + } + + // Handle generated code for WRITE operations + const generatedCode = parsed.FIX.GENERATE?.value; + if (generatedCode) { + this.applyGeneratedCode(result.operations, generatedCode); + } + + return result; + } + + private parseAction(action: any): FileOperation | null { + try { + switch (action.type.toUpperCase()) { + case 'WRITE': + return { + action: 'write', + path: this.sanitizePath(action.path), + originalPath: '', // Not used for write + content: '' // Temporarily empty + }; + case 'RENAME': + return { + action: 'rename', + path: this.sanitizePath(action.path), + originalPath: this.sanitizePath(action.ORIGINAL_PATH.value) + }; + default: + this.logger.warn(`Unknown action type: ${action.type}`); + return null; + } + } catch (error) { + this.logger.warn(`Invalid action format: ${JSON.stringify(action)}`); + return null; + } + } + + private applyGeneratedCode(operations: FileOperation[], code: string): void { + const writeOperations = operations.filter(op => op.action === 'write'); + if (writeOperations.length > 0) { + // Apply generated code to the first WRITE operation + writeOperations[0].content = code; + } + } + + private sanitizePath(rawPath: string): string { + const sanitized = path.normalize(rawPath) + .replace(/(\.\.\/|\.\.\\)/g, '') // Prevent path traversal + .replace(/^\/+/, '') // Remove leading slashes + .trim(); + + if (!sanitized) { + throw new Error(`Invalid path after sanitization: ${rawPath}`); + } + + return sanitized; + } +} \ No newline at end of file diff --git a/backend/src/build-system/handlers/frontend-code-generate/FrontendCodeValidator.ts b/backend/src/build-system/handlers/frontend-code-generate/FrontendCodeValidator.ts index cb6c4f24..761b9247 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FrontendCodeValidator.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FrontendCodeValidator.ts @@ -59,8 +59,7 @@ export class FrontendCodeValidator { // `Build process exited with code ${code}. Error: ${errorMessage}`, // ); - this.logger.error(`Build process exited with code 0.`); - // this.logger.error(`Build process exited with code ${code}.`); + this.logger.error(`Build process exited with code ${code}.`); resolve({ success: false, error: errorMessage, diff --git a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts index 49543cb1..b6726385 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts @@ -1,11 +1,14 @@ import { Logger } from '@nestjs/common'; import { FrontendCodeValidator } from './FrontendCodeValidator'; import { CodeTaskQueue, FileTask } from './CodeTaskQueue'; -import { readFileSync, writeFileSync } from 'fs'; +import { readFileSync } from 'fs'; import { chatSyncWithClocker } from 'src/build-system/utils/handler-helper'; import { createFileWithRetries } from 'src/build-system/utils/files'; import { BuilderContext } from 'src/build-system/context'; -import { formatResponse } from 'src/build-system/utils/strings'; +import { removeCodeBlockFences } from 'src/build-system/utils/strings'; +import { generateFileOperationPrompt } from './prompt'; +import { FileOperationManager } from './FileOperationManager'; +import { FixResponseParser } from './FixResponseParser'; export class FrontendQueueProcessor { private logger = new Logger('FrontendQueueProcessor'); @@ -24,11 +27,14 @@ export class FrontendQueueProcessor { const task = this.queue.dequeue(); if (!task) break; + // this.logger.debug('Task name: ' + task.filePath); await this.processSingleTask(task); this.logger.log(`Remaining tasks in queue: ${this.queue.size}`); } + // maybe need to requeue + this.logger.log('All tasks processed successfully!'); } @@ -66,7 +72,17 @@ export class FrontendQueueProcessor { ); // 3. Fix the file - await this.fixFileGeneric(task.filePath, validationResult.error ?? ''); + try { + await this.fixFileGeneric( + task.filePath, + validationResult.error ?? '', + task.dependenciesPath, + ); + } catch (error) { + this.logger.error( + 'Fix File Generic failed, get error: ' + error.messages, + ); + } // Now we loop back, re-run the build to see if it's fixed. } @@ -87,23 +103,26 @@ export class FrontendQueueProcessor { /** * Fallback if you have no structured error details. */ - private async fixFileGeneric(filePath: string, rawErrorText: string) { + private async fixFileGeneric( + filePath: string, + rawErrorText: string, + dependenciesPath: string, + ) { this.logger.log(`Generic fix attempt for file: ${filePath}`); const originalContent = readFileSync(filePath, 'utf-8'); - const fixPrompt = ` -We have a TypeScript build failure. The raw error text is: -\`\`\` -${rawErrorText} -\`\`\` + // const fixPrompt = generateFixPrompt( + // filePath, + // rawErrorText, + // dependenciesPath, + // originalContent, + // ); -The file content is: -\`\`\` -${originalContent} -\`\`\` + const fixPrompt = generateFileOperationPrompt(filePath, dependenciesPath); -Please fix the code so it compiles successfully. Return only the updated code wrapped in tags. -`; + const frontendPath = this.context.getGlobalContext('frontendPath'); + const fileOperationManager = new FileOperationManager(frontendPath); + const parser = new FixResponseParser(); //this.logger.log(fixPrompt); @@ -113,17 +132,38 @@ Please fix the code so it compiles successfully. Return only the updated code wr { model: 'gpt-4o', messages: [ - { role: 'system', content: 'You fix TypeScript code errors.' }, - { role: 'user', content: fixPrompt }, + { role: 'system', content: fixPrompt }, + { + role: 'user', + content: ` Current file path that need to be fix: \n ${filePath}`, + }, + { role: 'user', content: ` Error messages: \n ${rawErrorText}` }, + { + role: 'user', + content: ` dependency file Paths: \n ${dependenciesPath}`, + }, + { + role: 'user', + content: ` originalContent: \n ${originalContent}\n Now please start fix the problem and generate the result based on system prompt`, + }, ], }, 'fix code (generic)', 'FrontendQueueProcessor', ); + this.logger.log('Fix Response: ' + fixResponse); + const parsed_fixResponse = removeCodeBlockFences(fixResponse); + + // const { operations, generatedCode } = parser.parse(fixResponse); + + // await fileOperationManager.executeOperations(operations); + // this.logger.debug('Fix result' + fixResponse); - const updatedCode = formatResponse(fixResponse); - writeFileSync(filePath, updatedCode, 'utf-8'); + // remeber to do a retry here + // const updatedCode = removeCodeBlockFences(fixResponse); + + // writeFileSync(filePath, updatedCode, 'utf-8'); this.logger.log(`Generic fix applied to file: ${filePath}`); } } diff --git a/backend/src/build-system/handlers/frontend-code-generate/index.ts b/backend/src/build-system/handlers/frontend-code-generate/index.ts index b678e2fe..790eb0f7 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/index.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/index.ts @@ -33,13 +33,6 @@ import { FrontendCodeValidator } from './FrontendCodeValidator'; BackendRequirementHandler, FileFAHandler, ]) -@BuildNode() -@BuildNodeRequire([ - UXSMSHandler, - UXDMDHandler, - BackendRequirementHandler, - FileFAHandler, -]) export class FrontendCodeHandler implements BuildHandler { readonly logger: Logger = new Logger('FrontendCodeHandler'); private virtualDir: VirtualDirectory; @@ -120,6 +113,8 @@ export class FrontendCodeHandler implements BuildHandler { // Gather direct dependencies const directDepsArray = fileInfos[file]?.dependsOn || []; + const directDepsPathString = directDepsArray.join(', '); + // Read each dependency and append to dependenciesContext let dependenciesText = ''; for (const dep of directDepsArray) { @@ -227,6 +222,7 @@ export class FrontendCodeHandler implements BuildHandler { queue.enqueue({ filePath: currentFullFilePath, // relative path fileContents: generatedCode, + dependenciesPath: directDepsPathString, }); // 7. Write the file to the filesystem diff --git a/backend/src/build-system/handlers/frontend-code-generate/prompt.ts b/backend/src/build-system/handlers/frontend-code-generate/prompt.ts index bd7647bd..5c3ad4b3 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/prompt.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/prompt.ts @@ -90,3 +90,136 @@ export function generateCSSPrompt( `; } + +export function generateFixPrompt( + filePath: string, + rawErrorText: string, + dependenciesPath: string, + originalContent: string, +): string { + return ` + You are an expert in React and TypeScript. Your goal is to automatically fix errors in a given TypeScript React file while ensuring correctness, maintainability, and best practices. +**Instructions:** +1. **Understand the error from \`rawErrorText\`** and determine what's wrong. +2. **Analyze the dependencies** in \`dependenciesPath\` to ensure type compatibility. +3. **Modify the original code** in \`originalCode\` while preserving its logic. +4. **Ensure TypeScript type safety** and fix any possible runtime issues. +5. **Return only the fixed code and a concise explanation of the changes.** + +**User Inputs:** +- \`fileName\`: The file in which the error occurred. +- \`rawErrorText\`: The error message received. +- \`dependenciesPath\`: The full path to the dependencies directory. +- \`originalCode\`: The actual code with the error. + +**Expected Output:** +- Provide the **fixed code** without changing the structure unnecessarily. +- Ensure the code is TypeScript-safe and follows React best practices. +- Provide a **brief explanation** of the fixes and improvements. + +The file Name: + + ${filePath} + +The raw Error Text: +\`\`\` +${rawErrorText} +\`\`\` + +The dependency file path is: +\`\`\` +${dependenciesPath} +\`\`\` + +The file content is: +\`\`\` +${originalContent} +\`\`\` + +Please fix the code so it compiles successfully. Return only the updated code wrapped in tags. + `; +} + +export function generateFileOperationPrompt( + filePath: string, + dependenciesPath: string, +): string { + return ` + You are a senior developer fixing a TypeScript project. Analyze the error and choose appropriate file operations. + +Available Tools: +1. WRITE - Modify/create files +3. RENAME - RENAME the file + +**Instructions:** +1. **Understand the error from \`error\`** and determine what's wrong. +2. **Analyze the dependencies** in \`dependencies file path\` to ensure type compatibility. +3. **Modify the original code** in \`Current file Code\` while preserving its logic. +4. **Ensure TypeScript type safety** and fix any possible runtime issues. +5. Error Analysis: + - Read the error message carefully + - Identify error type (compilation/runtime/naming) + - Check if error originates from current file or dependencies + +6. Dependency Check: + - Compare types/interfaces with dependencies in: + ${dependenciesPath} + - Ensure all imports match actual exports + - Verify type signatures align + +7. Modification Rules: + - Preserve original functionality + - Maintain TypeScript strict mode compliance + - Keep existing code style/conventions + - Add type guards where necessary + - Prefer generics over 'any' + +8. File Operations: + - Use RENAME only for extension issues (e.g., .js → .tsx) + - Use WRITE for code/content changes + +9. In tag must include full code. + +**Some Common errors:** +1. file name jsx problem should use index.tsx use RENAME Tool +2. Typescript Type error should use WRITE Tool + +**safety check** +1. Never delete files outside /src directory +2. Keep original comments and JSDoc +3. Maintain existing export patterns +4. Verify all type references after changes + +**Expected Output format:** +Respond format: + + + + + + + + "src/old/path/here.js" + + + + + + + +**Good Tool using Example:** +Example Good WRITE Operation: + + +Example Good RENAME Operation: + + src/utils/helpers.js + + +**Important Note** +1.The output must be complete and strictly formatted. +2.DO NOT EXPLAIN OUTSIDE THE TAG. +3.Ensure that TypeScript code inside is NOT escaped. + + `; +} From 36f2f2e385eacc6fffbbb42b8834bb3353e9b141 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Tue, 4 Feb 2025 22:58:39 -0500 Subject: [PATCH 04/18] update to use json --- .../FileOperationManager.ts | 67 +++++---- .../FixResponseParser.ts | 112 ++++----------- .../FrontendQueueProcessor.ts | 127 ++++++++++-------- .../handlers/frontend-code-generate/index.ts | 16 +-- .../handlers/frontend-code-generate/prompt.ts | 110 ++++++++++----- 5 files changed, 203 insertions(+), 229 deletions(-) diff --git a/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts index 240eff87..0bbe2ea6 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts @@ -3,16 +3,9 @@ import { writeFile, rename } from 'fs/promises'; import path from 'path'; export interface FileOperation { - action: 'read' | 'write' | 'delete' | 'rename'; - path: string; - originalPath: string; - content?: string; - purpose?: string; -} - -export interface LLMFixResponse { - operations: FileOperation[]; - reasoning: string; + action: 'write' | 'rename'; + originalPath?: string; + renamePath?: string; code?: string; } @@ -33,44 +26,47 @@ export class FileOperationManager { // } for (const op of operations) { - const resolvedPath = path.resolve(this.projectRoot, op.path); - try { switch (op.action) { case 'write': - await this.handleWrite(resolvedPath, op); + await this.handleWrite(op); break; case 'rename': - await this.handleRename(resolvedPath, op); + await this.handleRename(op); break; } } catch (error) { - this.logger.error(`Failed to ${op.action} ${resolvedPath}: ${error}`); + this.logger.error( + `Failed to ${op.action} ${op.originalPath}: ${error}`, + ); throw error; } } } - private async handleWrite( - filePath: string, - op: FileOperation, - ): Promise { - this.safetyChecks(op); - await writeFile(filePath, op.content, 'utf-8'); + private async handleWrite(op: FileOperation): Promise { + const originalPath = path.resolve(this.projectRoot, op.originalPath); + this.safetyChecks(originalPath); + + this.logger.debug('start update file to: ' + originalPath); + await writeFile(originalPath, op.code, 'utf-8'); } - private async handleRename( - filePath: string, - op: FileOperation, - ): Promise { - this.safetyChecks(op); + private async handleRename(op: FileOperation): Promise { + const originalPath = path.resolve(this.projectRoot, op.originalPath); + const RenamePath = path.resolve(this.projectRoot, op.renamePath); + this.safetyChecks(originalPath); + this.safetyChecks(RenamePath); + + this.logger.debug('start rename: ' + originalPath); + this.logger.debug('change to name: ' + RenamePath); // Perform the actual rename - await rename(op.originalPath, filePath); + await rename(originalPath, RenamePath); } - private safetyChecks(op: FileOperation) { - const targetPath = path.resolve(this.projectRoot, op.path); // Normalize path + private safetyChecks(filePath: string) { + const targetPath = path.resolve(this.projectRoot, filePath); // Normalize path // Prevent path traversal attacks if (!targetPath.startsWith(this.projectRoot)) { @@ -78,7 +74,7 @@ export class FileOperationManager { } // Prevent package.json modifications - if (op.path.includes('package.json')) { + if (targetPath.includes('package.json')) { throw new Error('Modifying package.json requires special approval'); } @@ -87,13 +83,10 @@ export class FileOperationManager { throw new Error(`Attempted to access restricted path: ${targetPath}`); } - // Limit delete write operations - if ( - (op.action === 'delete' || op.action === 'write') && - !op.path.startsWith('src/') - ) { - throw new Error('Can only delete or write files in src/ directory'); - } + // Limit write anddelete write operations + // if (path.startsWith('src/')) { + // throw new Error('Can only delete or write files in src/ directory'); + // } } private isPathAllowed(targetPath: string): boolean { diff --git a/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts b/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts index 60b88440..c14e8625 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts @@ -1,103 +1,45 @@ -import { XMLParser } from 'fast-xml-parser'; -import { FileOperation, LLMFixResponse } from './FileOperationManager'; -import { Logger } from '@nestjs/common'; -import path from 'path'; +import { FileOperation } from './FileOperationManager'; export class FixResponseParser { - private readonly parser: XMLParser; - private readonly logger = new Logger('FixResponseParser'); + private logger = console; - constructor() { - this.parser = new XMLParser({ - ignoreAttributes: false, - attributeNamePrefix: '', - textNodeName: 'value', - allowBooleanAttributes: true, - alwaysCreateTextNode: true - }); - } + // parse the gpt json input + parse(json: string, filePath: string): FileOperation[] { + this.logger.log('Parsing JSON:', json); - parse(xml: string): LLMFixResponse { + let parsedData; try { - const parsed = this.parser.parse(xml); - return this.transformResponse(parsed); + parsedData = JSON.parse(json); } catch (error) { - this.logger.error('XML parsing failed', error.stack); - throw new Error('Invalid XML format from LLM'); - } - } - - private transformResponse(parsed: any): LLMFixResponse { - const result: LLMFixResponse = { - operations: [], - reasoning: '' - }; - - // Extract reasoning if available - result.reasoning = parsed.FIX.REASONING?.value || 'No reasoning provided'; - - // Process operations - const actions = parsed.FIX.OPERATIONS?.ACTION || []; - const actionsArray = Array.isArray(actions) ? actions : [actions]; - - for (const action of actionsArray) { - const operation = this.parseAction(action); - if (operation) result.operations.push(operation); + this.logger.error('Error parsing JSON:', error); + throw new Error('Invalid JSON format'); } - // Handle generated code for WRITE operations - const generatedCode = parsed.FIX.GENERATE?.value; - if (generatedCode) { - this.applyGeneratedCode(result.operations, generatedCode); + if (!parsedData.fix || !parsedData.fix.operations) { + throw new Error("Invalid JSON structure: Missing 'fix.operations'"); } - return result; - } - - private parseAction(action: any): FileOperation | null { - try { - switch (action.type.toUpperCase()) { - case 'WRITE': + const operations: FileOperation[] = parsedData.fix.operations + .map((op: any) => { + if (op.type === 'WRITE') { return { action: 'write', - path: this.sanitizePath(action.path), - originalPath: '', // Not used for write - content: '' // Temporarily empty + originalPath: filePath, + code: parsedData.fix.generate?.trim(), }; - case 'RENAME': + } else if (op.type === 'RENAME') { return { action: 'rename', - path: this.sanitizePath(action.path), - originalPath: this.sanitizePath(action.ORIGINAL_PATH.value) + originalPath: op.original_path, + renamePath: op.path, + code: parsedData.fix.generate?.trim(), }; - default: - this.logger.warn(`Unknown action type: ${action.type}`); - return null; - } - } catch (error) { - this.logger.warn(`Invalid action format: ${JSON.stringify(action)}`); - return null; - } - } - - private applyGeneratedCode(operations: FileOperation[], code: string): void { - const writeOperations = operations.filter(op => op.action === 'write'); - if (writeOperations.length > 0) { - // Apply generated code to the first WRITE operation - writeOperations[0].content = code; - } - } - - private sanitizePath(rawPath: string): string { - const sanitized = path.normalize(rawPath) - .replace(/(\.\.\/|\.\.\\)/g, '') // Prevent path traversal - .replace(/^\/+/, '') // Remove leading slashes - .trim(); - - if (!sanitized) { - throw new Error(`Invalid path after sanitization: ${rawPath}`); - } + } + return null; + }) + .filter(Boolean); - return sanitized; + this.logger.log('Extracted operations:', operations); + return operations; } -} \ No newline at end of file +} diff --git a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts index b6726385..501b4113 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts @@ -6,10 +6,16 @@ import { chatSyncWithClocker } from 'src/build-system/utils/handler-helper'; import { createFileWithRetries } from 'src/build-system/utils/files'; import { BuilderContext } from 'src/build-system/context'; import { removeCodeBlockFences } from 'src/build-system/utils/strings'; -import { generateFileOperationPrompt } from './prompt'; +import { + generateCommonErrorPrompt, + generateFileOperationPrompt, +} from './prompt'; import { FileOperationManager } from './FileOperationManager'; import { FixResponseParser } from './FixResponseParser'; +import normalizePath from 'normalize-path'; +import path from 'path'; + export class FrontendQueueProcessor { private logger = new Logger('FrontendQueueProcessor'); @@ -17,6 +23,7 @@ export class FrontendQueueProcessor { private validator: FrontendCodeValidator, // Path to your frontend project private queue: CodeTaskQueue, private context: BuilderContext, // The queue of files to process + private frontendPath: string, ) {} /** @@ -27,7 +34,6 @@ export class FrontendQueueProcessor { const task = this.queue.dequeue(); if (!task) break; - // this.logger.debug('Task name: ' + task.filePath); await this.processSingleTask(task); this.logger.log(`Remaining tasks in queue: ${this.queue.size}`); @@ -47,8 +53,12 @@ export class FrontendQueueProcessor { private async processSingleTask(task: FileTask): Promise { this.logger.log(`Processing file task: ${task.filePath}`); + const currentFullFilePath = normalizePath( + path.resolve(this.frontendPath, task.filePath), + ); + // 1. Write the file to disk - createFileWithRetries(task.filePath, task.fileContents); + createFileWithRetries(currentFullFilePath, task.fileContents); const maxFixAttempts = 3; @@ -74,6 +84,7 @@ export class FrontendQueueProcessor { // 3. Fix the file try { await this.fixFileGeneric( + currentFullFilePath, task.filePath, validationResult.error ?? '', task.dependenciesPath, @@ -83,12 +94,9 @@ export class FrontendQueueProcessor { 'Fix File Generic failed, get error: ' + error.messages, ); } - - // Now we loop back, re-run the build to see if it's fixed. } // If we reached here, we failed all attempts - // if we want to end all generate // throw new Error( // `Failed to fix build for file ${task.filePath} after ${maxFixAttempts} attempts.`, @@ -104,66 +112,67 @@ export class FrontendQueueProcessor { * Fallback if you have no structured error details. */ private async fixFileGeneric( + currentFullFilePath: string, filePath: string, rawErrorText: string, dependenciesPath: string, ) { - this.logger.log(`Generic fix attempt for file: ${filePath}`); - const originalContent = readFileSync(filePath, 'utf-8'); - - // const fixPrompt = generateFixPrompt( - // filePath, - // rawErrorText, - // dependenciesPath, - // originalContent, - // ); - - const fixPrompt = generateFileOperationPrompt(filePath, dependenciesPath); - - const frontendPath = this.context.getGlobalContext('frontendPath'); - const fileOperationManager = new FileOperationManager(frontendPath); - const parser = new FixResponseParser(); - - //this.logger.log(fixPrompt); - - // Use model for a fix - const fixResponse = await chatSyncWithClocker( - this.context, - { - model: 'gpt-4o', - messages: [ - { role: 'system', content: fixPrompt }, - { - role: 'user', - content: ` Current file path that need to be fix: \n ${filePath}`, - }, - { role: 'user', content: ` Error messages: \n ${rawErrorText}` }, - { - role: 'user', - content: ` dependency file Paths: \n ${dependenciesPath}`, - }, - { - role: 'user', - content: ` originalContent: \n ${originalContent}\n Now please start fix the problem and generate the result based on system prompt`, - }, - ], - }, - 'fix code (generic)', - 'FrontendQueueProcessor', - ); - - this.logger.log('Fix Response: ' + fixResponse); - const parsed_fixResponse = removeCodeBlockFences(fixResponse); + try { + this.logger.log(`Generic fix attempt for file: ${currentFullFilePath}`); + const originalContent = readFileSync(currentFullFilePath, 'utf-8'); + + const fixPrompt = generateFileOperationPrompt(); + const commonIssuePrompt = generateCommonErrorPrompt(); + + const fileOperationManager = new FileOperationManager(this.frontendPath); + const parser = new FixResponseParser(); + + //this.logger.log(fixPrompt); + + // Use model for a fix + const fixResponse = await chatSyncWithClocker( + this.context, + { + model: 'gpt-4o', + messages: [ + { role: 'system', content: fixPrompt }, + { + role: 'user', + content: ` Current file path that need to be fix: \n ${filePath}`, + }, + { role: 'user', content: ` Error messages: \n ${rawErrorText}` }, + { + role: 'user', + content: ` dependency file Paths: \n ${dependenciesPath}`, + }, + { + role: 'user', + content: ` originalContent: \n ${originalContent}\n Now please start fix the problem and generate the result based on system prompt`, + }, + { + role: 'assistant', + content: `Do this really fix the provide code? + Let me check some common issue to make sure my answer is correct ${commonIssuePrompt}. If not I should modify the result. + If i am using rename tool am i use the correct Current file path for it? + I must follow the output format.`, + }, + ], + }, + 'fix code (generic)', + 'FrontendQueueProcessor', + ); - // const { operations, generatedCode } = parser.parse(fixResponse); + this.logger.debug('Fix Response: ' + fixResponse); + this.logger.debug('dependency file Paths ' + dependenciesPath); + const parsed_fixResponse = removeCodeBlockFences(fixResponse); - // await fileOperationManager.executeOperations(operations); + const operations = parser.parse(parsed_fixResponse, filePath); - // this.logger.debug('Fix result' + fixResponse); - // remeber to do a retry here - // const updatedCode = removeCodeBlockFences(fixResponse); + await fileOperationManager.executeOperations(operations); - // writeFileSync(filePath, updatedCode, 'utf-8'); - this.logger.log(`Generic fix applied to file: ${filePath}`); + this.logger.log(`Generic fix applied to file: ${filePath}`); + } catch (error) { + this.logger.error('Generic Fix file: ' + error.message); + } } } diff --git a/backend/src/build-system/handlers/frontend-code-generate/index.ts b/backend/src/build-system/handlers/frontend-code-generate/index.ts index 790eb0f7..ef868d6f 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/index.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/index.ts @@ -105,11 +105,6 @@ export class FrontendCodeHandler implements BuildHandler { `Layer #${layerIndex + 1}, generating code for file: ${file}`, ); - // Resolve the absolute path where this file should be generated - const currentFullFilePath = normalizePath( - path.resolve(frontendPath, file), - ); // src - // Gather direct dependencies const directDepsArray = fileInfos[file]?.dependsOn || []; @@ -220,18 +215,10 @@ export class FrontendCodeHandler implements BuildHandler { // 7. Add the file to the queue for writing queue.enqueue({ - filePath: currentFullFilePath, // relative path + filePath: file, // relative path fileContents: generatedCode, dependenciesPath: directDepsPathString, }); - - // 7. Write the file to the filesystem - // await createFileWithRetries( - // currentFullFilePath, - // generatedCode, - // maxRetries, - // delayMs, - // ); } catch (err) { this.logger.error(`Error generating code for ${file}:`, err); // FIXME: remove this later @@ -271,6 +258,7 @@ export class FrontendCodeHandler implements BuildHandler { validator, queue, context, + frontendPath, ); await queueProcessor.processAllTasks(); diff --git a/backend/src/build-system/handlers/frontend-code-generate/prompt.ts b/backend/src/build-system/handlers/frontend-code-generate/prompt.ts index 5c3ad4b3..dd6fc288 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/prompt.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/prompt.ts @@ -140,16 +140,13 @@ Please fix the code so it compiles successfully. Return only the updated code wr `; } -export function generateFileOperationPrompt( - filePath: string, - dependenciesPath: string, -): string { +export function generateFileOperationPrompt(): string { return ` - You are a senior developer fixing a TypeScript project. Analyze the error and choose appropriate file operations. + You are a senior developer fixing a TypeScript project. Analyze the error and choose appropriate file operations. Return a structured JSON object that contains the fix. Available Tools: 1. WRITE - Modify/create files -3. RENAME - RENAME the file +2. RENAME - RENAME the file **Instructions:** 1. **Understand the error from \`error\`** and determine what's wrong. @@ -162,8 +159,7 @@ Available Tools: - Check if error originates from current file or dependencies 6. Dependency Check: - - Compare types/interfaces with dependencies in: - ${dependenciesPath} + - Compare types/interfaces with dependencies file path provide by user. - Ensure all imports match actual exports - Verify type signatures align @@ -178,48 +174,94 @@ Available Tools: - Use RENAME only for extension issues (e.g., .js → .tsx) - Use WRITE for code/content changes -9. In tag must include full code. +9.generate must include full code. + -**Some Common errors:** -1. file name jsx problem should use index.tsx use RENAME Tool -2. Typescript Type error should use WRITE Tool +**Common Errors & Fixes** + JSX file naming issue → Use the RENAME tool. + TypeScript type error → Use the WRITE tool. **safety check** 1. Never delete files outside /src directory -2. Keep original comments and JSDoc 3. Maintain existing export patterns 4. Verify all type references after changes -**Expected Output format:** -Respond format: +**Output format:** +Respond format in this json format: + +{ + "fix": { + "operations": [ + { + "type": "WRITE" + }, + { + "type": "RENAME", + "path": "src/new/path/here.tsx", + "original_path": "src/old/path/here.ts" + } + ], + "generate": " Code here " + } +} + - - - - - - - "src/old/path/here.js" - - - - - - **Good Tool using Example:** Example Good WRITE Operation: - +{ + "fix": { + "operations": [ + { + "type": "WRITE" + } + ], + "generate": " Code here " + } +} Example Good RENAME Operation: - - src/utils/helpers.js - +{ + "fix": { + "operations": [ + { + "type": "RENAME", + "path": "src/utils/helpers.tsx", + "original_path": "src/utils/helpers.js" + } + ], + "generate": "" + } +} **Important Note** 1.The output must be complete and strictly formatted. -2.DO NOT EXPLAIN OUTSIDE THE TAG. -3.Ensure that TypeScript code inside is NOT escaped. +2.DO NOT EXPLAIN OUTSIDE JSON. `; } + +export function generateCommonErrorPrompt(): string { + return ` + 1. JSX File Naming Issue → Use the RENAME Tool + +Error Example: + Cannot find namespace ''.ts + Operator '<' cannot be applied to types 'boolean' and 'RegExp' + +Fix: + + Rename .ts to .tsx since JSX syntax requires TypeScript support. + +✅ Correct Fix Output: + + + + + src/components/Button.ts + + + + + `; +} From b1d2bbffe68d04b953f4cc4164a059bdd2fef288 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Wed, 5 Feb 2025 21:35:03 -0500 Subject: [PATCH 05/18] update template --- backend/template/react-ts/package.json | 2 ++ backend/template/react-ts/src/index.tsx | 5 +++++ backend/template/react-ts/tsconfig.node.json | 2 +- backend/template/react-ts/vite.config.ts | 6 ++++++ 4 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 backend/template/react-ts/src/index.tsx diff --git a/backend/template/react-ts/package.json b/backend/template/react-ts/package.json index 1cd08629..2c6d31cc 100644 --- a/backend/template/react-ts/package.json +++ b/backend/template/react-ts/package.json @@ -11,9 +11,11 @@ }, "dependencies": { "@tailwindcss/vite": "^4.0.0", + "axios": "^1.7.9", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router": "^6.28.2", + "react-router-dom": "^7.1.5", "tailwindcss": "^4.0.0" }, "devDependencies": { diff --git a/backend/template/react-ts/src/index.tsx b/backend/template/react-ts/src/index.tsx new file mode 100644 index 00000000..ce7a60ab --- /dev/null +++ b/backend/template/react-ts/src/index.tsx @@ -0,0 +1,5 @@ +import ReactDOM from "react-dom/client"; + +const App = () =>

Hello, CodeFox!

; + +ReactDOM.createRoot(document.getElementById("root")!).render(); diff --git a/backend/template/react-ts/tsconfig.node.json b/backend/template/react-ts/tsconfig.node.json index db0becc8..b6da3843 100644 --- a/backend/template/react-ts/tsconfig.node.json +++ b/backend/template/react-ts/tsconfig.node.json @@ -14,7 +14,7 @@ "noEmit": true, /* Linting */ - "strict": true, + "strict": false, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, diff --git a/backend/template/react-ts/vite.config.ts b/backend/template/react-ts/vite.config.ts index 603ac5e9..09bfddc5 100644 --- a/backend/template/react-ts/vite.config.ts +++ b/backend/template/react-ts/vite.config.ts @@ -10,4 +10,10 @@ export default defineConfig({ '@': path.resolve(__dirname, './src'), }, }, + esbuild: { + target: 'esnext', // Allow top-level await + }, + build: { + target: 'esnext', // Ensure Vite compiles for a modern target + }, }); From 59af23457462c4631cce1131a551af92e3bb2745 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Wed, 5 Feb 2025 21:35:29 -0500 Subject: [PATCH 06/18] Fix bug --- .../FileOperationManager.ts | 7 ++- .../FixResponseParser.ts | 2 +- .../FrontendQueueProcessor.ts | 51 +++++++++++++------ 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts index 0bbe2ea6..2dd21415 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts @@ -20,11 +20,13 @@ export class FileOperationManager { } private operationCount = 0; - async executeOperations(operations: FileOperation[]): Promise { + async executeOperations(operations: FileOperation[]): Promise { // if (operations.length > 5) { // throw new Error('Maximum 5 operations per fix'); // } + let newFilePath: string | null = null; + for (const op of operations) { try { switch (op.action) { @@ -33,6 +35,7 @@ export class FileOperationManager { break; case 'rename': await this.handleRename(op); + newFilePath = op.renamePath || null; break; } } catch (error) { @@ -42,6 +45,8 @@ export class FileOperationManager { throw error; } } + + return newFilePath; } private async handleWrite(op: FileOperation): Promise { diff --git a/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts b/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts index c14e8625..0aca8755 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts @@ -39,7 +39,7 @@ export class FixResponseParser { }) .filter(Boolean); - this.logger.log('Extracted operations:', operations); + // this.logger.log('Extracted operations:', operations); return operations; } } diff --git a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts index 501b4113..9d5c4f51 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts @@ -21,8 +21,8 @@ export class FrontendQueueProcessor { constructor( private validator: FrontendCodeValidator, // Path to your frontend project - private queue: CodeTaskQueue, - private context: BuilderContext, // The queue of files to process + private queue: CodeTaskQueue, // The queue of files to process + private context: BuilderContext, private frontendPath: string, ) {} @@ -53,7 +53,7 @@ export class FrontendQueueProcessor { private async processSingleTask(task: FileTask): Promise { this.logger.log(`Processing file task: ${task.filePath}`); - const currentFullFilePath = normalizePath( + let currentFullFilePath = normalizePath( path.resolve(this.frontendPath, task.filePath), ); @@ -83,12 +83,24 @@ export class FrontendQueueProcessor { // 3. Fix the file try { - await this.fixFileGeneric( + const newFilePath = await this.fixFileGeneric( currentFullFilePath, - task.filePath, + task, validationResult.error ?? '', - task.dependenciesPath, ); + + if (newFilePath !== null) { + this.logger.log( + `File was renamed: ${task.filePath} → ${newFilePath}`, + ); + task.filePath = newFilePath; + currentFullFilePath = normalizePath( + path.resolve(this.frontendPath, newFilePath), + ); + this.logger.log( + `Updated currentFullFilePath: ${currentFullFilePath}`, + ); + } } catch (error) { this.logger.error( 'Fix File Generic failed, get error: ' + error.messages, @@ -113,14 +125,15 @@ export class FrontendQueueProcessor { */ private async fixFileGeneric( currentFullFilePath: string, - filePath: string, + task: FileTask, rawErrorText: string, - dependenciesPath: string, - ) { + ): Promise { try { this.logger.log(`Generic fix attempt for file: ${currentFullFilePath}`); const originalContent = readFileSync(currentFullFilePath, 'utf-8'); + this.logger.debug('raw error: ' + rawErrorText); + const fixPrompt = generateFileOperationPrompt(); const commonIssuePrompt = generateCommonErrorPrompt(); @@ -138,12 +151,12 @@ export class FrontendQueueProcessor { { role: 'system', content: fixPrompt }, { role: 'user', - content: ` Current file path that need to be fix: \n ${filePath}`, + content: ` Current file path that need to be fix: \n ${task.filePath}`, }, { role: 'user', content: ` Error messages: \n ${rawErrorText}` }, { role: 'user', - content: ` dependency file Paths: \n ${dependenciesPath}`, + content: ` dependency file Paths: \n ${task.dependenciesPath}`, }, { role: 'user', @@ -163,14 +176,22 @@ export class FrontendQueueProcessor { ); this.logger.debug('Fix Response: ' + fixResponse); - this.logger.debug('dependency file Paths ' + dependenciesPath); + this.logger.debug('dependency file Paths ' + task.dependenciesPath); const parsed_fixResponse = removeCodeBlockFences(fixResponse); - const operations = parser.parse(parsed_fixResponse, filePath); + const operations = parser.parse(parsed_fixResponse, task.filePath); + + const newFilePath = + await fileOperationManager.executeOperations(operations); - await fileOperationManager.executeOperations(operations); + this.logger.log(`Generic fix applied to file: ${task.filePath}`); + + if (newFilePath) { + this.logger.log(`File was renamed: ${task.filePath} → ${newFilePath}`); + return newFilePath; + } - this.logger.log(`Generic fix applied to file: ${filePath}`); + return null; } catch (error) { this.logger.error('Generic Fix file: ' + error.message); } From 8f7db08496f4b10bd79bc9cb3b9f7cd6d35e7b83 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 6 Feb 2025 02:37:01 +0000 Subject: [PATCH 07/18] [autofix.ci] apply automated fixes --- backend/template/react-ts/src/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/template/react-ts/src/index.tsx b/backend/template/react-ts/src/index.tsx index ce7a60ab..f9fdd442 100644 --- a/backend/template/react-ts/src/index.tsx +++ b/backend/template/react-ts/src/index.tsx @@ -1,5 +1,5 @@ -import ReactDOM from "react-dom/client"; +import ReactDOM from 'react-dom/client'; const App = () =>

Hello, CodeFox!

; -ReactDOM.createRoot(document.getElementById("root")!).render(); +ReactDOM.createRoot(document.getElementById('root')!).render(); From 0bfcf378b6bd8422dd36d782d1599fd2669795eb Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Wed, 5 Feb 2025 23:09:57 -0500 Subject: [PATCH 08/18] refector to make code easier to read --- .../handlers/frontend-code-generate/index.ts | 295 ++++++++++-------- 1 file changed, 170 insertions(+), 125 deletions(-) diff --git a/backend/src/build-system/handlers/frontend-code-generate/index.ts b/backend/src/build-system/handlers/frontend-code-generate/index.ts index ef868d6f..4ca5a95b 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/index.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/index.ts @@ -19,8 +19,14 @@ import { writeFileSync } from 'fs'; import { MessageInterface } from 'src/common/model-provider/types'; import { CodeTaskQueue } from './CodeTaskQueue'; -import { FrontendQueueProcessor } from './FrontendQueueProcessor'; import { FrontendCodeValidator } from './FrontendCodeValidator'; +import { FrontendQueueProcessor } from './FrontendQueueProcessor'; + +interface FileInfos { + [fileName: string]: { + dependsOn: string[]; + }; +} /** * FrontendCodeHandler is responsible for generating the frontend codebase * based on the provided sitemap, data mapping documents, backend requirement documents, @@ -71,7 +77,7 @@ export class FrontendCodeHandler implements BuildHandler { throw new Error('Missing required parameters.'); } - // Dependency + // 3. Prepare for Dependency const { concurrencyLayers, fileInfos } = await generateFilesDependencyWithLayers(fileArchDoc, this.virtualDir); @@ -105,133 +111,48 @@ export class FrontendCodeHandler implements BuildHandler { `Layer #${layerIndex + 1}, generating code for file: ${file}`, ); + const currentFullFilePath = normalizePath( + path.resolve(frontendPath, file), + ); + // Gather direct dependencies const directDepsArray = fileInfos[file]?.dependsOn || []; - const directDepsPathString = directDepsArray.join(', '); + const directDepsPathString = directDepsArray.join('\n'); // Read each dependency and append to dependenciesContext - let dependenciesText = ''; - for (const dep of directDepsArray) { - this.logger.log( - `Layer #${layerIndex + 1}, file "${file}" → reading dependency "${dep}"`, - ); - try { - // need to check if it really reflect the real path - const resolvedDepPath = normalizePath( - path.resolve(frontendPath, dep), - ); - - // Read the content of the dependency file - const depContent = await readFileWithRetries( - resolvedDepPath, - maxRetries, - delayMs, - ); - - dependenciesText += `\n\n File path: ${dep} \n\`\`\`typescript\n${depContent}\n\`\`\`\n `; - } catch (err) { - this.logger.warn( - `Failed to read dependency "${dep}" for file "${file}": ${err}`, - ); - } - } - - // 5. Build prompt text depending on file extension - const fileExtension = path.extname(file); - let frontendCodePrompt = ''; - if (fileExtension === '.css') { - frontendCodePrompt = generateCSSPrompt( - file, - directDepsArray.join('\n'), - ); - } else { - // default: treat as e.g. .ts, .js, .vue, .jsx, etc. - frontendCodePrompt = generateFrontEndCodePrompt( - file, - directDepsArray.join('\n'), - ); - } - // this.logger.log( - // `Prompt for file "${file}":\n${frontendCodePrompt}\n`, - // ); + const dependenciesText = await this.gatherDependenciesForFile( + file, + fileInfos, + frontendPath, + ); - const messages = [ - { - role: 'system' as const, - content: frontendCodePrompt, - }, - { - role: 'user' as const, - content: `**Sitemap Structure** - ${sitemapStruct} - `, - }, - // To DO need to dynamically add the UX Datamap Documentation and Backend Requirement Documentation based on the file generate - // { - // role: 'user' as const, - // content: `This is the UX Datamap Documentation: - // ${uxDataMapDoc} - - // Next will provide UX Datamap Documentation.`, - // }, - // { - // role: 'user' as const, - // content: `This is the Backend Requirement Documentation: - // ${backendRequirementDoc} - - // Next will provide Backend Requirement Documentation.`, - // }, - { - role: 'assistant', - content: - "Good, now provider your dependencies, it's okay dependencies are empty, which means you don't have any dependencies", - }, - { - role: 'user' as const, - content: `Dependencies: - - ${dependenciesText}\n - Now you can provide the code, don't forget the xml tags. -, `, - }, - ] as MessageInterface[]; - - // 6. Call your Chat Model - let generatedCode = ''; - let modelResponse = ''; - try { - modelResponse = await chatSyncWithClocker( - context, - { - model: 'gpt-4o', - messages, - }, - 'generate frontend code', - FrontendCodeHandler.name, - ); - - generatedCode = formatResponse(modelResponse); - - // 7. Add the file to the queue for writing - queue.enqueue({ - filePath: file, // relative path - fileContents: generatedCode, - dependenciesPath: directDepsPathString, - }); - } catch (err) { - this.logger.error(`Error generating code for ${file}:`, err); - // FIXME: remove this later - failedFiles.push( - JSON.stringify({ - file: file, - error: err, - modelResponse, - generatedCode, - messages, - }), - ); - } + this.logger.debug('dependency: ' + directDepsPathString); + + // generate code + const generatedCode = await this.generateFileCode( + context, + file, + dependenciesText, + directDepsPathString, + sitemapStruct, + uxDataMapDoc, + failedFiles, + ); + + // 7. Add the file to the queue for writing + queue.enqueue({ + filePath: file, // relative path + fileContents: generatedCode, + dependenciesPath: directDepsPathString, + }); + + // await createFileWithRetries( + // currentFullFilePath, + // generatedCode, + // maxRetries, + // delayMs, + // ); }), ); @@ -252,8 +173,8 @@ export class FrontendCodeHandler implements BuildHandler { } } - // B) Now process the entire queue for this layer: - // This writes each file, runs build, fixes if needed, etc. + // Now process the entire queue for this layer: + // This writes each file, runs build, fixes if needed, etc. const queueProcessor = new FrontendQueueProcessor( validator, queue, @@ -273,4 +194,128 @@ export class FrontendCodeHandler implements BuildHandler { error: new Error('Frontend code generated and parsed successfully.'), }; } + + // get the dependencies content and path + private async gatherDependenciesForFile( + file: string, + fileInfos: FileInfos, + frontendPath: string, + ): Promise { + const directDepsArray = fileInfos[file]?.dependsOn ?? []; + let dependenciesText = ''; + + for (const dep of directDepsArray) { + try { + const resolvedDepPath = normalizePath(path.resolve(frontendPath, dep)); + const depContent = await readFileWithRetries(resolvedDepPath, 3, 200); + dependenciesText += `\n\n File path: ${dep}\n\`\`\`typescript\n${depContent}\n\`\`\`\n`; + } catch (err) { + this.logger.warn( + `Failed to read dependency "${dep}" for file "${file}"`, + err, + ); + } + } + + return dependenciesText; + } + + // Generate File Code + private async generateFileCode( + context: BuilderContext, + file: string, + dependenciesText: string, + directDepsPathString: string, + sitemapStruct: string, + uxDataMapDoc: string, + failedFiles: any[], + ): Promise { + let generatedCode = ''; + let modelResponse = ''; + let messages = []; + try { + const fileExtension = path.extname(file); + let frontendCodePrompt = ''; + if (fileExtension === '.css') { + frontendCodePrompt = generateCSSPrompt(file, directDepsPathString); + } else { + // default: treat as e.g. .ts, .js, .vue, .jsx, etc. + frontendCodePrompt = generateFrontEndCodePrompt( + file, + directDepsPathString, + ); + } + // this.logger.log( + // `Prompt for file "${file}":\n${frontendCodePrompt}\n`, + // ); + + messages = [ + { + role: 'system' as const, + content: frontendCodePrompt, + }, + { + role: 'user' as const, + content: `**Sitemap Structure** + ${sitemapStruct} + `, + }, + // To DO need to dynamically add the UX Datamap Documentation and Backend Requirement Documentation based on the file generate + // { + // role: 'user' as const, + // content: `This is the UX Datamap Documentation: + // ${uxDataMapDoc} + + // Next will provide UX Datamap Documentation.`, + // }, + // { + // role: 'user' as const, + // content: `This is the Backend Requirement Documentation: + // ${backendRequirementDoc} + + // Next will provide Backend Requirement Documentation.`, + // }, + { + role: 'assistant', + content: + "Good, now provider your dependencies, it's okay dependencies are empty, which means you don't have any dependencies", + }, + { + role: 'user' as const, + content: `Dependencies: + + ${dependenciesText}\n + Now you can provide the code, don't forget the xml tags. +, `, + }, + ] as MessageInterface[]; + + // 6. Call your Chat Model + modelResponse = await chatSyncWithClocker( + context, + { + model: 'gpt-4o', + messages, + }, + 'generate frontend code', + FrontendCodeHandler.name, + ); + + generatedCode = formatResponse(modelResponse); + + return generatedCode; + } catch (err) { + this.logger.error(`Error generating code for ${file}:`, err); + // FIXME: remove this later + failedFiles.push( + JSON.stringify({ + file: file, + error: err, + modelResponse, + generatedCode, + messages, + }), + ); + } + } } From 0be6af5831a536d9950876f014d2eb7ce18f6fea Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Fri, 7 Feb 2025 23:42:52 -0500 Subject: [PATCH 09/18] add read operation --- .../FileOperationManager.ts | 29 ++++++- .../FixResponseParser.ts | 5 ++ .../FrontendQueueProcessor.ts | 75 ++++++++++++++++++- .../handlers/frontend-code-generate/prompt.ts | 55 +++++++++++++- 4 files changed, 158 insertions(+), 6 deletions(-) diff --git a/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts index 2dd21415..4ff52b69 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts @@ -1,9 +1,9 @@ import { Logger } from '@nestjs/common'; -import { writeFile, rename } from 'fs/promises'; +import { writeFile, rename, readFile } from 'fs/promises'; import path from 'path'; export interface FileOperation { - action: 'write' | 'rename'; + action: 'write' | 'rename' | 'read'; originalPath?: string; renamePath?: string; code?: string; @@ -37,6 +37,10 @@ export class FileOperationManager { await this.handleRename(op); newFilePath = op.renamePath || null; break; + case 'read': + await this.handleRead(op); + newFilePath = op.renamePath || null; + break; } } catch (error) { this.logger.error( @@ -57,6 +61,27 @@ export class FileOperationManager { await writeFile(originalPath, op.code, 'utf-8'); } + private async handleRead(op: FileOperation): Promise { + try { + const originalPath = path.resolve(this.projectRoot, op.originalPath); + this.safetyChecks(originalPath); + + this.logger.debug(`Reading file: ${originalPath}`); + + // Read the file content + const fileContent = await readFile(originalPath, 'utf-8'); + + this.logger.debug(`File read successfully: ${originalPath}`); + + return fileContent; + } catch (error) { + this.logger.error( + `Failed to read file: ${op.originalPath}, Error: ${error.message}`, + ); + return null; // Return null if the file cannot be read + } + } + private async handleRename(op: FileOperation): Promise { const originalPath = path.resolve(this.projectRoot, op.originalPath); const RenamePath = path.resolve(this.projectRoot, op.renamePath); diff --git a/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts b/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts index 0aca8755..8469856e 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts @@ -34,6 +34,11 @@ export class FixResponseParser { renamePath: op.path, code: parsedData.fix.generate?.trim(), }; + } else if (op.type === 'READ') { + return { + action: 'read', + originalPath: op.original_path, + }; } return null; }) diff --git a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts index 9d5c4f51..b6dd2d9a 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts @@ -60,7 +60,7 @@ export class FrontendQueueProcessor { // 1. Write the file to disk createFileWithRetries(currentFullFilePath, task.fileContents); - const maxFixAttempts = 3; + const maxFixAttempts = 2; for (let attempt = 1; attempt <= maxFixAttempts; attempt++) { const validationResult = await this.validator.validate(); @@ -143,7 +143,7 @@ export class FrontendQueueProcessor { //this.logger.log(fixPrompt); // Use model for a fix - const fixResponse = await chatSyncWithClocker( + let fixResponse = await chatSyncWithClocker( this.context, { model: 'gpt-4o', @@ -179,7 +179,76 @@ export class FrontendQueueProcessor { this.logger.debug('dependency file Paths ' + task.dependenciesPath); const parsed_fixResponse = removeCodeBlockFences(fixResponse); - const operations = parser.parse(parsed_fixResponse, task.filePath); + let operations = parser.parse(parsed_fixResponse, task.filePath); + + // **If LLM requested additional files, read them** + if (operations.some((op) => op.action === 'read')) { + this.logger.log( + `LLM requested additional context. Reading dependencies...`, + ); + + for (const op of operations) { + if (op.action === 'read' && op.originalPath) { + try { + op.code = readFileSync( + path.resolve(this.frontendPath, op.originalPath), + 'utf-8', + ); + this.logger.log(`Read file: ${op.originalPath}`); + } catch (error) { + this.logger.warn( + `Failed to read file: ${op.originalPath}. Error: ${error.message}`, + ); + } + } + } + + // **Second Attempt: Retry fix with additional file content** + fixResponse = await chatSyncWithClocker( + this.context, + { + model: 'gpt-4o', + messages: [ + { role: 'system', content: fixPrompt }, + { + role: 'user', + content: `Current file path that needs fixing: \n ${task.filePath}`, + }, + { role: 'user', content: `Error messages: \n ${rawErrorText}` }, + { + role: 'user', + content: ` dependency file Paths: \n ${task.dependenciesPath}`, + }, + { + role: 'user', + content: `Original content:\n ${originalContent}`, + }, + { + role: 'user', + content: `Additional imported files:\n ${operations + .filter((op) => op.action === 'read' && op.code) + .map((op) => `File: ${op.originalPath}\nContent:\n${op.code}`) + .join('\n\n')}`, + }, + { + role: 'assistant', + content: `Do this really fix the provide code? + This time I shouldn't use the read tool because previous context already use it. + Let me check some common issue to make sure my answer is correct ${commonIssuePrompt}. If not I should modify the result. + If i am using rename tool am i use the correct Current file path for it? + I must follow the output format.`, + }, + ], + }, + 'fix code (generic)', + 'FrontendQueueProcessor', + ); + this.logger.debug( + 'Updated Fix Response with extra context: ' + fixResponse, + ); + const updated_fixResponse = removeCodeBlockFences(fixResponse); + operations = await parser.parse(updated_fixResponse, task.filePath); + } const newFilePath = await fileOperationManager.executeOperations(operations); diff --git a/backend/src/build-system/handlers/frontend-code-generate/prompt.ts b/backend/src/build-system/handlers/frontend-code-generate/prompt.ts index dd6fc288..543e605c 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/prompt.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/prompt.ts @@ -147,6 +147,7 @@ export function generateFileOperationPrompt(): string { Available Tools: 1. WRITE - Modify/create files 2. RENAME - RENAME the file +3. READ - Read the file **Instructions:** 1. **Understand the error from \`error\`** and determine what's wrong. @@ -173,13 +174,17 @@ Available Tools: 8. File Operations: - Use RENAME only for extension issues (e.g., .js → .tsx) - Use WRITE for code/content changes + - Use READ for not enough information so solve the issue -9.generate must include full code. +9. When User provide "Additional imported files" use this as to help you fix the error. Remeber only write other files code to current file when it is necessary + +10. generate must include full code. **Common Errors & Fixes** JSX file naming issue → Use the RENAME tool. TypeScript type error → Use the WRITE tool. + Not assignable to parameter of type → Use the READ tool if you dont have enough information to fix. **safety check** 1. Never delete files outside /src directory @@ -200,6 +205,10 @@ Respond format in this json format: "path": "src/new/path/here.tsx", "original_path": "src/old/path/here.ts" } + { + "type": "READ", + "original_path": "src/the/path/read.tsx" + } ], "generate": " Code here " } @@ -234,6 +243,20 @@ Example Good RENAME Operation: } } +Example Good READ Operation: +{ + "fix": { + "operations": [ + { + "type": "READ", + "original_path": "src/utils/helpers.tsx", + } + ... You can ask to read more then one file. + ], + "generate": "" + } +} + **Important Note** 1.The output must be complete and strictly formatted. 2.DO NOT EXPLAIN OUTSIDE JSON. @@ -263,5 +286,35 @@ Fix:
+ +2. defined but never used Issue -> Use the WRITE Tool + +Error example: + 'useEffect' is defined but never used. + +Fix: + Remove the defined but never used component from the import. + +✅ Correct Fix Output: + { + "fix": { + "operations": [ + { + "type": "WRITE" + } + ], + "generate": "Do the fix for the import and other part stay the same and put Full code here!" + } + } + + +3. Import error -> Use the WRITE Tool + +Error example: + Cannot find module './components/GlobalFooter' or its corresponding type declarations. + +Fix: + Read carefully about previous "dependency file Paths" use the path in the fix if applicable. + `; } From af42fff283e047c0ad89b30db24f9f3bd5076023 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Thu, 13 Feb 2025 17:00:39 -0500 Subject: [PATCH 10/18] add rename map to help match dependencies file name --- .../handlers/frontend-code-generate/index.ts | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/backend/src/build-system/handlers/frontend-code-generate/index.ts b/backend/src/build-system/handlers/frontend-code-generate/index.ts index 4ca5a95b..b5f152c6 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/index.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/index.ts @@ -77,6 +77,8 @@ export class FrontendCodeHandler implements BuildHandler { throw new Error('Missing required parameters.'); } + const renameMap = new Map(); + // 3. Prepare for Dependency const { concurrencyLayers, fileInfos } = await generateFilesDependencyWithLayers(fileArchDoc, this.virtualDir); @@ -116,7 +118,15 @@ export class FrontendCodeHandler implements BuildHandler { ); // Gather direct dependencies - const directDepsArray = fileInfos[file]?.dependsOn || []; + let directDepsArray = fileInfos[file]?.dependsOn || []; + + // Replace old file names in dependencies with new ones + directDepsArray = directDepsArray.map( + (dep) => renameMap.get(dep) || dep, + ); + + // **Ensure the fileInfos structure is also updated** + fileInfos[file].dependsOn = directDepsArray; const directDepsPathString = directDepsArray.join('\n'); @@ -180,6 +190,7 @@ export class FrontendCodeHandler implements BuildHandler { queue, context, frontendPath, + renameMap, ); await queueProcessor.processAllTasks(); @@ -235,6 +246,7 @@ export class FrontendCodeHandler implements BuildHandler { let messages = []; try { const fileExtension = path.extname(file); + let frontendCodePrompt = ''; if (fileExtension === '.css') { frontendCodePrompt = generateCSSPrompt(file, directDepsPathString); @@ -256,7 +268,7 @@ export class FrontendCodeHandler implements BuildHandler { }, { role: 'user' as const, - content: `**Sitemap Structure** + content: `## Sitemap Structure ${sitemapStruct} `, }, @@ -282,12 +294,23 @@ export class FrontendCodeHandler implements BuildHandler { }, { role: 'user' as const, - content: `Dependencies: - - ${dependenciesText}\n - Now you can provide the code, don't forget the xml tags. -, `, + content: ` + + ## Overview of The Dependencies file you may need + ${directDepsPathString} + + ## Detail about each Dependencies: + ${dependenciesText}\n + `, }, + { + role: 'user', + content: `Now you can provide the code, don't forget the tags.`, + }, + // { + // role: 'assistant', + // content: codeReviewPrompt, + // }, ] as MessageInterface[]; // 6. Call your Chat Model From 72667311ed41779a8ab165469976a5a2594bb782 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Thu, 13 Feb 2025 17:02:02 -0500 Subject: [PATCH 11/18] add rename map path --- .../FileOperationManager.ts | 15 +++++- .../FrontendQueueProcessor.ts | 54 ++++++++++++------- 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts index 4ff52b69..7f0981aa 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts @@ -14,7 +14,10 @@ export class FileOperationManager { private readonly allowedPaths: string[]; private logger = new Logger('FileOperationManager'); - constructor(projectRoot: string) { + constructor( + projectRoot: string, + private renameMap: Map, + ) { this.projectRoot = path.normalize(projectRoot); this.allowedPaths = [this.projectRoot]; } @@ -36,6 +39,16 @@ export class FileOperationManager { case 'rename': await this.handleRename(op); newFilePath = op.renamePath || null; + + // add new file path + if (op.originalPath && op.renamePath) { + // **Check if originalPath was previously renamed** + const latestPath = + this.renameMap.get(op.originalPath) || op.originalPath; + + // **Update mapping for the latest renamed file** + this.renameMap.set(latestPath, op.renamePath); + } break; case 'read': await this.handleRead(op); diff --git a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts index b6dd2d9a..9d8fc6b9 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts @@ -24,6 +24,7 @@ export class FrontendQueueProcessor { private queue: CodeTaskQueue, // The queue of files to process private context: BuilderContext, private frontendPath: string, + private renameMap: Map, ) {} /** @@ -137,7 +138,10 @@ export class FrontendQueueProcessor { const fixPrompt = generateFileOperationPrompt(); const commonIssuePrompt = generateCommonErrorPrompt(); - const fileOperationManager = new FileOperationManager(this.frontendPath); + const fileOperationManager = new FileOperationManager( + this.frontendPath, + this.renameMap, + ); const parser = new FixResponseParser(); //this.logger.log(fixPrompt); @@ -151,23 +155,29 @@ export class FrontendQueueProcessor { { role: 'system', content: fixPrompt }, { role: 'user', - content: ` Current file path that need to be fix: \n ${task.filePath}`, + content: ` ## Current file: \n ${task.filePath} ## Current Code \n ${originalContent}\n `, }, - { role: 'user', content: ` Error messages: \n ${rawErrorText}` }, { role: 'user', - content: ` dependency file Paths: \n ${task.dependenciesPath}`, + content: ` ## Error Messages: \n ${rawErrorText}`, + }, + { + role: 'assistant', + content: + "Good, now provider your dependencies, it's okay dependencies are empty, which means you don't have any dependencies", }, { role: 'user', - content: ` originalContent: \n ${originalContent}\n Now please start fix the problem and generate the result based on system prompt`, + content: `## Overview of The Dependencies file you may need: \n ${task.dependenciesPath}`, }, { role: 'assistant', - content: `Do this really fix the provide code? - Let me check some common issue to make sure my answer is correct ${commonIssuePrompt}. If not I should modify the result. - If i am using rename tool am i use the correct Current file path for it? - I must follow the output format.`, + content: `Let me analysis the current file. Why error message occour? + Let me check some common issue to make sure my thinking is correct ${commonIssuePrompt}.`, + }, + { + role: 'user', + content: `Now you should start fix the current code error.`, }, ], }, @@ -212,31 +222,34 @@ export class FrontendQueueProcessor { { role: 'system', content: fixPrompt }, { role: 'user', - content: `Current file path that needs fixing: \n ${task.filePath}`, + content: ` ## Current file: \n ${task.filePath} ## Current Code \n ${originalContent}\n `, }, - { role: 'user', content: `Error messages: \n ${rawErrorText}` }, { role: 'user', - content: ` dependency file Paths: \n ${task.dependenciesPath}`, + content: `## Error messages: \n ${rawErrorText}`, }, { - role: 'user', - content: `Original content:\n ${originalContent}`, + role: 'assistant', + content: + "Good, now provider your dependencies, it's okay dependencies are empty, which means you don't have any dependencies", }, { role: 'user', - content: `Additional imported files:\n ${operations + content: `## Overview of The Dependencies files: \n ${task.dependenciesPath}\n + # Additional imported files:\n ${operations .filter((op) => op.action === 'read' && op.code) .map((op) => `File: ${op.originalPath}\nContent:\n${op.code}`) .join('\n\n')}`, }, { role: 'assistant', - content: `Do this really fix the provide code? - This time I shouldn't use the read tool because previous context already use it. - Let me check some common issue to make sure my answer is correct ${commonIssuePrompt}. If not I should modify the result. - If i am using rename tool am i use the correct Current file path for it? - I must follow the output format.`, + content: `Let me analysis the current file. Why error message occour + This time I shouldn't use the read tool because previous context already use it. + Let me check some common issue to make sure my thinking is correct ${commonIssuePrompt}.`, + }, + { + role: 'user', + content: `Now you should start fix the current code error.`, }, ], }, @@ -263,6 +276,7 @@ export class FrontendQueueProcessor { return null; } catch (error) { this.logger.error('Generic Fix file: ' + error.message); + return null; } } } From 998c609c380b0d29272eba334e98d4f3328b917c Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Fri, 14 Feb 2025 15:19:19 -0500 Subject: [PATCH 12/18] udpate template --- backend/template/react-ts/index.html | 8 +- backend/template/react-ts/package-lock.json | 942 +++++++++----------- 2 files changed, 419 insertions(+), 531 deletions(-) diff --git a/backend/template/react-ts/index.html b/backend/template/react-ts/index.html index 4208b1f9..6b16f407 100644 --- a/backend/template/react-ts/index.html +++ b/backend/template/react-ts/index.html @@ -8,12 +8,6 @@
- + diff --git a/backend/template/react-ts/package-lock.json b/backend/template/react-ts/package-lock.json index 67438768..3f8dc453 100644 --- a/backend/template/react-ts/package-lock.json +++ b/backend/template/react-ts/package-lock.json @@ -9,9 +9,11 @@ "version": "0.0.0", "dependencies": { "@tailwindcss/vite": "^4.0.0", + "axios": "^1.7.9", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router": "^6.28.2", + "react-router-dom": "^7.1.5", "tailwindcss": "^4.0.0" }, "devDependencies": { @@ -34,7 +36,6 @@ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, - "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -48,7 +49,6 @@ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", @@ -63,7 +63,6 @@ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -73,7 +72,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz", "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", "dev": true, - "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -104,7 +102,6 @@ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/parser": "^7.26.5", "@babel/types": "^7.26.5", @@ -121,7 +118,6 @@ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/compat-data": "^7.26.5", "@babel/helper-validator-option": "^7.25.9", @@ -138,7 +134,6 @@ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" @@ -152,7 +147,6 @@ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9", @@ -170,7 +164,6 @@ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -180,7 +173,6 @@ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -190,7 +182,6 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -200,7 +191,6 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -210,7 +200,6 @@ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.7.tgz", "integrity": "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==", "dev": true, - "license": "MIT", "dependencies": { "@babel/template": "^7.25.9", "@babel/types": "^7.26.7" @@ -224,7 +213,6 @@ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.26.7" }, @@ -240,7 +228,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -256,7 +243,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -272,7 +258,6 @@ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/code-frame": "^7.25.9", "@babel/parser": "^7.25.9", @@ -287,7 +272,6 @@ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz", "integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.5", @@ -306,7 +290,6 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -316,7 +299,6 @@ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz", "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" @@ -332,7 +314,6 @@ "cpu": [ "ppc64" ], - "license": "MIT", "optional": true, "os": [ "aix" @@ -348,7 +329,6 @@ "cpu": [ "arm" ], - "license": "MIT", "optional": true, "os": [ "android" @@ -364,7 +344,6 @@ "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "android" @@ -380,7 +359,6 @@ "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "android" @@ -396,7 +374,6 @@ "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "darwin" @@ -412,7 +389,6 @@ "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "darwin" @@ -428,7 +404,6 @@ "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "freebsd" @@ -444,7 +419,6 @@ "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "freebsd" @@ -460,7 +434,6 @@ "cpu": [ "arm" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -476,7 +449,6 @@ "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -492,7 +464,6 @@ "cpu": [ "ia32" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -508,7 +479,6 @@ "cpu": [ "loong64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -524,7 +494,6 @@ "cpu": [ "mips64el" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -540,7 +509,6 @@ "cpu": [ "ppc64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -556,7 +524,6 @@ "cpu": [ "riscv64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -572,7 +539,6 @@ "cpu": [ "s390x" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -588,7 +554,6 @@ "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -604,7 +569,6 @@ "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "netbsd" @@ -620,7 +584,6 @@ "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "netbsd" @@ -636,7 +599,6 @@ "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "openbsd" @@ -652,7 +614,6 @@ "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "openbsd" @@ -668,7 +629,6 @@ "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "sunos" @@ -684,7 +644,6 @@ "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "win32" @@ -700,7 +659,6 @@ "cpu": [ "ia32" ], - "license": "MIT", "optional": true, "os": [ "win32" @@ -716,7 +674,6 @@ "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "win32" @@ -730,7 +687,6 @@ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, - "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.4.3" }, @@ -749,7 +705,6 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -762,19 +717,17 @@ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, - "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/config-array": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", - "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", + "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.5", + "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -787,7 +740,6 @@ "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" }, @@ -800,7 +752,6 @@ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, - "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -824,7 +775,6 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -837,17 +787,15 @@ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "dev": true, - "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", - "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -857,7 +805,6 @@ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", "dev": true, - "license": "Apache-2.0", "dependencies": { "@eslint/core": "^0.10.0", "levn": "^0.4.1" @@ -871,7 +818,6 @@ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=18.18.0" } @@ -881,7 +827,6 @@ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, - "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" @@ -895,7 +840,6 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -909,7 +853,6 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -923,7 +866,6 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -937,7 +879,6 @@ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -952,7 +893,6 @@ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -962,7 +902,6 @@ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -971,15 +910,13 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -990,7 +927,6 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1004,7 +940,6 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "license": "MIT", "engines": { "node": ">= 8" } @@ -1014,7 +949,6 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -1024,302 +958,279 @@ } }, "node_modules/@remix-run/router": { - "version": "1.21.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.1.tgz", - "integrity": "sha512-KeBYSwohb8g4/wCcnksvKTYlg69O62sQeLynn2YE+5z7JWEj95if27kclW9QqbrlsQ2DINI8fjbV3zyuKfwjKg==", - "license": "MIT", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.22.0.tgz", + "integrity": "sha512-MBOl8MeOzpK0HQQQshKB7pABXbmyHizdTpqnrIseTbsv0nAepwC2ENZa1aaBExNQcpLoXmWthhak8SABLzvGPw==", "engines": { "node": ">=14.0.0" } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.0.tgz", - "integrity": "sha512-G2fUQQANtBPsNwiVFg4zKiPQyjVKZCUdQUol53R8E71J7AsheRMV/Yv/nB8giOcOVqP7//eB5xPqieBYZe9bGg==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.4.tgz", + "integrity": "sha512-gGi5adZWvjtJU7Axs//CWaQbQd/vGy8KGcnEaCWiyCqxWYDxwIlAHFuSe6Guoxtd0SRvSfVTDMPd5H+4KE2kKA==", "cpu": [ "arm" ], - "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.0.tgz", - "integrity": "sha512-qhFwQ+ljoymC+j5lXRv8DlaJYY/+8vyvYmVx074zrLsu5ZGWYsJNLjPPVJJjhZQpyAKUGPydOq9hRLLNvh1s3A==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.4.tgz", + "integrity": "sha512-1aRlh1gqtF7vNPMnlf1vJKk72Yshw5zknR/ZAVh7zycRAGF2XBMVDAHmFQz/Zws5k++nux3LOq/Ejj1WrDR6xg==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.0.tgz", - "integrity": "sha512-44n/X3lAlWsEY6vF8CzgCx+LQaoqWGN7TzUfbJDiTIOjJm4+L2Yq+r5a8ytQRGyPqgJDs3Rgyo8eVL7n9iW6AQ==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.4.tgz", + "integrity": "sha512-drHl+4qhFj+PV/jrQ78p9ch6A0MfNVZScl/nBps5a7u01aGf/GuBRrHnRegA9bP222CBDfjYbFdjkIJ/FurvSQ==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.0.tgz", - "integrity": "sha512-F9ct0+ZX5Np6+ZDztxiGCIvlCaW87HBdHcozUfsHnj1WCUTBUubAoanhHUfnUHZABlElyRikI0mgcw/qdEm2VQ==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.4.tgz", + "integrity": "sha512-hQqq/8QALU6t1+fbNmm6dwYsa0PDD4L5r3TpHx9dNl+aSEMnIksHZkSO3AVH+hBMvZhpumIGrTFj8XCOGuIXjw==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.0.tgz", - "integrity": "sha512-JpsGxLBB2EFXBsTLHfkZDsXSpSmKD3VxXCgBQtlPcuAqB8TlqtLcbeMhxXQkCDv1avgwNjF8uEIbq5p+Cee0PA==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.4.tgz", + "integrity": "sha512-/L0LixBmbefkec1JTeAQJP0ETzGjFtNml2gpQXA8rpLo7Md+iXQzo9kwEgzyat5Q+OG/C//2B9Fx52UxsOXbzw==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "freebsd" ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.0.tgz", - "integrity": "sha512-wegiyBT6rawdpvnD9lmbOpx5Sph+yVZKHbhnSP9MqUEDX08G4UzMU+D87jrazGE7lRSyTRs6NEYHtzfkJ3FjjQ==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.4.tgz", + "integrity": "sha512-6Rk3PLRK+b8L/M6m/x6Mfj60LhAUcLJ34oPaxufA+CfqkUrDoUPQYFdRrhqyOvtOKXLJZJwxlOLbQjNYQcRQfw==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "freebsd" ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.0.tgz", - "integrity": "sha512-3pA7xecItbgOs1A5H58dDvOUEboG5UfpTq3WzAdF54acBbUM+olDJAPkgj1GRJ4ZqE12DZ9/hNS2QZk166v92A==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.4.tgz", + "integrity": "sha512-kmT3x0IPRuXY/tNoABp2nDvI9EvdiS2JZsd4I9yOcLCCViKsP0gB38mVHOhluzx+SSVnM1KNn9k6osyXZhLoCA==", "cpu": [ "arm" ], - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.0.tgz", - "integrity": "sha512-Y7XUZEVISGyge51QbYyYAEHwpGgmRrAxQXO3siyYo2kmaj72USSG8LtlQQgAtlGfxYiOwu+2BdbPjzEpcOpRmQ==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.4.tgz", + "integrity": "sha512-3iSA9tx+4PZcJH/Wnwsvx/BY4qHpit/u2YoZoXugWVfc36/4mRkgGEoRbRV7nzNBSCOgbWMeuQ27IQWgJ7tRzw==", "cpu": [ "arm" ], - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.0.tgz", - "integrity": "sha512-r7/OTF5MqeBrZo5omPXcTnjvv1GsrdH8a8RerARvDFiDwFpDVDnJyByYM/nX+mvks8XXsgPUxkwe/ltaX2VH7w==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.4.tgz", + "integrity": "sha512-7CwSJW+sEhM9sESEk+pEREF2JL0BmyCro8UyTq0Kyh0nu1v0QPNY3yfLPFKChzVoUmaKj8zbdgBxUhBRR+xGxg==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.0.tgz", - "integrity": "sha512-HJbifC9vex9NqnlodV2BHVFNuzKL5OnsV2dvTw6e1dpZKkNjPG6WUq+nhEYV6Hv2Bv++BXkwcyoGlXnPrjAKXw==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.4.tgz", + "integrity": "sha512-GZdafB41/4s12j8Ss2izofjeFXRAAM7sHCb+S4JsI9vaONX/zQ8cXd87B9MRU/igGAJkKvmFmJJBeeT9jJ5Cbw==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.0.tgz", - "integrity": "sha512-VAEzZTD63YglFlWwRj3taofmkV1V3xhebDXffon7msNz4b14xKsz7utO6F8F4cqt8K/ktTl9rm88yryvDpsfOw==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.4.tgz", + "integrity": "sha512-uuphLuw1X6ur11675c2twC6YxbzyLSpWggvdawTUamlsoUv81aAXRMPBC1uvQllnBGls0Qt5Siw8reSIBnbdqQ==", "cpu": [ "loong64" ], - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.0.tgz", - "integrity": "sha512-Sts5DST1jXAc9YH/iik1C9QRsLcCoOScf3dfbY5i4kH9RJpKxiTBXqm7qU5O6zTXBTEZry69bGszr3SMgYmMcQ==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.4.tgz", + "integrity": "sha512-KvLEw1os2gSmD6k6QPCQMm2T9P2GYvsMZMRpMz78QpSoEevHbV/KOUbI/46/JRalhtSAYZBYLAnT9YE4i/l4vg==", "cpu": [ "ppc64" ], - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.0.tgz", - "integrity": "sha512-qhlXeV9AqxIyY9/R1h1hBD6eMvQCO34ZmdYvry/K+/MBs6d1nRFLm6BOiITLVI+nFAAB9kUB6sdJRKyVHXnqZw==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.4.tgz", + "integrity": "sha512-wcpCLHGM9yv+3Dql/CI4zrY2mpQ4WFergD3c9cpRowltEh5I84pRT/EuHZsG0In4eBPPYthXnuR++HrFkeqwkA==", "cpu": [ "riscv64" ], - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.0.tgz", - "integrity": "sha512-8ZGN7ExnV0qjXa155Rsfi6H8M4iBBwNLBM9lcVS+4NcSzOFaNqmt7djlox8pN1lWrRPMRRQ8NeDlozIGx3Omsw==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.4.tgz", + "integrity": "sha512-nLbfQp2lbJYU8obhRQusXKbuiqm4jSJteLwfjnunDT5ugBKdxqw1X9KWwk8xp1OMC6P5d0WbzxzhWoznuVK6XA==", "cpu": [ "s390x" ], - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.32.0.tgz", - "integrity": "sha512-VDzNHtLLI5s7xd/VubyS10mq6TxvZBp+4NRWoW+Hi3tgV05RtVm4qK99+dClwTN1McA6PHwob6DEJ6PlXbY83A==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.4.tgz", + "integrity": "sha512-JGejzEfVzqc/XNiCKZj14eb6s5w8DdWlnQ5tWUbs99kkdvfq9btxxVX97AaxiUX7xJTKFA0LwoS0KU8C2faZRg==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.32.0.tgz", - "integrity": "sha512-qcb9qYDlkxz9DxJo7SDhWxTWV1gFuwznjbTiov289pASxlfGbaOD54mgbs9+z94VwrXtKTu+2RqwlSTbiOqxGg==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.4.tgz", + "integrity": "sha512-/iFIbhzeyZZy49ozAWJ1ZR2KW6ZdYUbQXLT4O5n1cRZRoTpwExnHLjlurDXXPKEGxiAg0ujaR9JDYKljpr2fDg==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.0.tgz", - "integrity": "sha512-pFDdotFDMXW2AXVbfdUEfidPAk/OtwE/Hd4eYMTNVVaCQ6Yl8et0meDaKNL63L44Haxv4UExpv9ydSf3aSayDg==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.4.tgz", + "integrity": "sha512-qORc3UzoD5UUTneiP2Afg5n5Ti1GAW9Gp5vHPxzvAFFA3FBaum9WqGvYXGf+c7beFdOKNos31/41PRMUwh1tpA==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.0.tgz", - "integrity": "sha512-/TG7WfrCAjeRNDvI4+0AAMoHxea/USWhAzf9PVDFHbcqrQ7hMMKp4jZIy4VEjk72AAfN5k4TiSMRXRKf/0akSw==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.4.tgz", + "integrity": "sha512-5g7E2PHNK2uvoD5bASBD9aelm44nf1w4I5FEI7MPHLWcCSrR8JragXZWgKPXk5i2FU3JFfa6CGZLw2RrGBHs2Q==", "cpu": [ "ia32" ], - "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.32.0.tgz", - "integrity": "sha512-5hqO5S3PTEO2E5VjCePxv40gIgyS2KvO7E7/vvC/NbIW4SIRamkMr1hqj+5Y67fbBWv/bQLB6KelBQmXlyCjWA==", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.4.tgz", + "integrity": "sha512-p0scwGkR4kZ242xLPBuhSckrJ734frz6v9xZzD+kHVYRAkSUmdSLCIJRfql6H5//aF8Q10K+i7q8DiPfZp0b7A==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@tailwindcss/node": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.0.0.tgz", - "integrity": "sha512-tfG2uBvo6j6kDIPmntxwXggCOZAt7SkpAXJ6pTIYirNdk5FBqh/CZZ9BZPpgcl/tNFLs6zc4yghM76sqiELG9g==", - "license": "MIT", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.0.3.tgz", + "integrity": "sha512-QsVJokOl0pJ4AbJV33D2npvLcHGPWi5MOSZtrtE0GT3tSx+3D0JE2lokLA8yHS1x3oCY/3IyRyy7XX6tmzid7A==", "dependencies": { "enhanced-resolve": "^5.18.0", "jiti": "^2.4.2", - "tailwindcss": "4.0.0" + "tailwindcss": "4.0.3" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.0.0.tgz", - "integrity": "sha512-W3FjpJgy4VV1JiL7iBYDf2n/WkeDg1Il+0Q7eWnqPyvkPPCo/Mbwc5BiaT7dfBNV6tQKAhVE34rU5xl8pSl50w==", - "license": "MIT", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.0.3.tgz", + "integrity": "sha512-FFcp3VNvRjjmFA39ORM27g2mbflMQljhvM7gxBAujHxUy4LXlKa6yMF9wbHdTbPqTONiCyyOYxccvJyVyI/XBg==", "engines": { "node": ">= 10" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.0.0", - "@tailwindcss/oxide-darwin-arm64": "4.0.0", - "@tailwindcss/oxide-darwin-x64": "4.0.0", - "@tailwindcss/oxide-freebsd-x64": "4.0.0", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.0.0", - "@tailwindcss/oxide-linux-arm64-gnu": "4.0.0", - "@tailwindcss/oxide-linux-arm64-musl": "4.0.0", - "@tailwindcss/oxide-linux-x64-gnu": "4.0.0", - "@tailwindcss/oxide-linux-x64-musl": "4.0.0", - "@tailwindcss/oxide-win32-arm64-msvc": "4.0.0", - "@tailwindcss/oxide-win32-x64-msvc": "4.0.0" + "@tailwindcss/oxide-android-arm64": "4.0.3", + "@tailwindcss/oxide-darwin-arm64": "4.0.3", + "@tailwindcss/oxide-darwin-x64": "4.0.3", + "@tailwindcss/oxide-freebsd-x64": "4.0.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.0.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.0.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.0.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.0.3", + "@tailwindcss/oxide-linux-x64-musl": "4.0.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.0.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.0.3" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.0.0.tgz", - "integrity": "sha512-EAhjU0+FIdyGPR+7MbBWubLLPtmOu+p7c2egTTFBRk/n//zYjNvVK0WhcBK5Y7oUB5mo4EjA2mCbY7dcEMWSRw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.0.3.tgz", + "integrity": "sha512-S8XOTQuMnpijZRlPm5HBzPJjZ28quB+40LSRHjRnQF6rRYKsvpr1qkY7dfwsetNdd+kMLOMDsvmuT8WnqqETvg==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "android" @@ -1329,13 +1240,12 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.0.0.tgz", - "integrity": "sha512-hdz4xnSWS11cIp+7ye+3dGHqs0X33z+BXXTtgPOguDWVa+TdXUzwxonklSzf5wlJFuot3dv5eWzhlNai0oYYQg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.0.3.tgz", + "integrity": "sha512-smrY2DpzhXvgDhZtQlYAl8+vxJ04lv2/64C1eiRxvsRT2nkw/q+zA1/eAYKvUHat6cIuwqDku3QucmrUT6pCeg==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "darwin" @@ -1345,13 +1255,12 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.0.0.tgz", - "integrity": "sha512-+dOUUaXTkPKKhtUI9QtVaYg+MpmLh2CN0dHohiYXaBirEyPMkjaT0zbRgzQlNnQWjCVVXPQluIEb0OMEjSTH+Q==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.0.3.tgz", + "integrity": "sha512-NTz8x/LcGUjpZAWUxz0ZuzHao90Wj9spoQgomwB+/hgceh5gcJDfvaBYqxLFpKzVglpnbDSq1Fg0p0zI4oa5Pg==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "darwin" @@ -1361,13 +1270,12 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.0.0.tgz", - "integrity": "sha512-CJhGDhxnrmu4SwyC62fA+wP24MhA/TZlIhRHqg1kRuIHoGoVR2uSSm1qxTxU37tSSZj8Up0q6jsBJCAP4k7rgQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.0.3.tgz", + "integrity": "sha512-yQc9Q0JCOp3kkAV8gKgDctXO60IkQhHpqGB+KgOccDtD5UmN6Q5+gd+lcsDyQ7N8dRuK1fAud51xQpZJgKfm7g==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "freebsd" @@ -1377,13 +1285,12 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.0.0.tgz", - "integrity": "sha512-Wy7Av0xzXfY2ujZBcYy4+7GQm25/J1iHvlQU2CfwdDCuPWfIjYzR6kggz+uVdSJyKV2s64znchBxRE8kV4uXSA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.0.3.tgz", + "integrity": "sha512-e1ivVMLSnxTOU1O3npnxN16FEyWM/g3SuH2pP6udxXwa0/SnSAijRwcAYRpqIlhVKujr158S8UeHxQjC4fGl4w==", "cpu": [ "arm" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -1393,13 +1300,12 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.0.0.tgz", - "integrity": "sha512-srwBo2l6pvM0swBntc1ucuhGsfFOLkqPRFQ3dWARRTfSkL1U9nAsob2MKc/n47Eva/W9pZZgMOuf7rDw8pK1Ew==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.0.3.tgz", + "integrity": "sha512-PLrToqQqX6sdJ9DmMi8IxZWWrfjc9pdi9AEEPTrtMts3Jm9HBi1WqEeF1VwZZ2aW9TXloE5OwA35zuuq1Bhb/Q==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -1409,13 +1315,12 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.0.0.tgz", - "integrity": "sha512-abhusswkduYWuezkBmgo0K0/erGq3M4Se5xP0fhc/0dKs0X/rJUYYCFWntHb3IGh3aVzdQ0SXJs93P76DbUqtw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.0.3.tgz", + "integrity": "sha512-YlzRxx7N1ampfgSKzEDw0iwDkJXUInR4cgNEqmR4TzHkU2Vhg59CGPJrTI7dxOBofD8+O35R13Nk9Ytyv0JUFg==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -1425,13 +1330,12 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.0.0.tgz", - "integrity": "sha512-hGtRYIUEx377/HlU49+jvVKKwU1MDSKYSMMs0JFO2Wp7LGxk5+0j5+RBk9NFnmp/lbp32yPTgIOO5m1BmDq36A==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.0.3.tgz", + "integrity": "sha512-Xfc3z/li6XkuD7Hs+Uk6pjyCXnfnd9zuQTKOyDTZJ544xc2yoMKUkuDw6Et9wb31MzU2/c0CIUpTDa71lL9KHw==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -1441,13 +1345,12 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.0.0.tgz", - "integrity": "sha512-7xgQgSAThs0I14VAgmxpJnK6XFSZBxHMGoDXkLyYkEnu+8WRQMbCP93dkCUn2PIv+Q+JulRgc00PJ09uORSLXQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.0.3.tgz", + "integrity": "sha512-ugKVqKzwa/cjmqSQG17aS9DYrEcQ/a5NITcgmOr3JLW4Iz64C37eoDlkC8tIepD3S/Td/ywKAolTQ8fKbjEL4g==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -1457,13 +1360,12 @@ } }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.0.0.tgz", - "integrity": "sha512-qEcgTIPcWY5ZE7f6VxQ/JPrSFMcehzVIlZj7sGE3mVd5YWreAT+Fl1vSP8q2pjnWXn0avZG3Iw7a2hJQAm+fTQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.0.3.tgz", + "integrity": "sha512-qHPDMl+UUwsk1RMJMgAXvhraWqUUT+LR/tkXix5RA39UGxtTrHwsLIN1AhNxI5i2RFXAXfmFXDqZCdyQ4dWmAQ==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "win32" @@ -1473,13 +1375,12 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.0.0.tgz", - "integrity": "sha512-bqT0AY8RXb8GMDy28JtngvqaOSB2YixbLPLvUo6I6lkvvUwA6Eqh2Tj60e2Lh7O/k083f8tYiB0WEK4wmTI7Jg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.0.3.tgz", + "integrity": "sha512-+ujwN4phBGyOsPyLgGgeCyUm4Mul+gqWVCIGuSXWgrx9xVUnf6LVXrw0BDBc9Aq1S2qMyOTX4OkCGbZeoIo8Qw==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "win32" @@ -1489,15 +1390,14 @@ } }, "node_modules/@tailwindcss/vite": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.0.0.tgz", - "integrity": "sha512-4uukMiU9gHui8KMPMdWic5SP1O/tmQ1NFSRNrQWmcop5evAVl/LZ6/LuWL3quEiecp2RBcRWwqJrG+mFXlRlew==", - "license": "MIT", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.0.3.tgz", + "integrity": "sha512-Qj6rSO+EvXnNDymloKZ11D54JJTnDrkRWJBzNHENDxjt0HtrCZJbSLIrcJ/WdaoU4othrel/oFqHpO/doxIS/Q==", "dependencies": { - "@tailwindcss/node": "^4.0.0", - "@tailwindcss/oxide": "^4.0.0", + "@tailwindcss/node": "^4.0.3", + "@tailwindcss/oxide": "^4.0.3", "lightningcss": "^1.29.1", - "tailwindcss": "4.0.0" + "tailwindcss": "4.0.3" }, "peerDependencies": { "vite": "^5.2.0 || ^6" @@ -1508,7 +1408,6 @@ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -1522,7 +1421,6 @@ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" } @@ -1532,7 +1430,6 @@ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, - "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -1543,30 +1440,31 @@ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dev": true, - "license": "MIT", "dependencies": { "@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==" + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "license": "MIT" + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/node": { - "version": "22.12.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.12.0.tgz", - "integrity": "sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==", + "version": "22.13.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", + "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", "devOptional": true, - "license": "MIT", "dependencies": { "undici-types": "~6.20.0" } @@ -1575,15 +1473,13 @@ "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/react": { "version": "18.3.18", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", "dev": true, - "license": "MIT", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -1594,27 +1490,25 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz", "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", "dev": true, - "license": "MIT", "peerDependencies": { "@types/react": "^18.0.0" } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.22.0.tgz", - "integrity": "sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz", + "integrity": "sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.22.0", - "@typescript-eslint/type-utils": "8.22.0", - "@typescript-eslint/utils": "8.22.0", - "@typescript-eslint/visitor-keys": "8.22.0", + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/type-utils": "8.23.0", + "@typescript-eslint/utils": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1630,16 +1524,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.22.0.tgz", - "integrity": "sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz", + "integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.22.0", - "@typescript-eslint/types": "8.22.0", - "@typescript-eslint/typescript-estree": "8.22.0", - "@typescript-eslint/visitor-keys": "8.22.0", + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/typescript-estree": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "debug": "^4.3.4" }, "engines": { @@ -1655,14 +1548,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.22.0.tgz", - "integrity": "sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.23.0.tgz", + "integrity": "sha512-OGqo7+dXHqI7Hfm+WqkZjKjsiRtFUQHPdGMXzk5mYXhJUedO7e/Y7i8AK3MyLMgZR93TX4bIzYrfyVjLC+0VSw==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.22.0", - "@typescript-eslint/visitor-keys": "8.22.0" + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1673,16 +1565,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.22.0.tgz", - "integrity": "sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.23.0.tgz", + "integrity": "sha512-iIuLdYpQWZKbiH+RkCGc6iu+VwscP5rCtQ1lyQ7TYuKLrcZoeJVpcLiG8DliXVkUxirW/PWlmS+d6yD51L9jvA==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.22.0", - "@typescript-eslint/utils": "8.22.0", + "@typescript-eslint/typescript-estree": "8.23.0", + "@typescript-eslint/utils": "8.23.0", "debug": "^4.3.4", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1697,11 +1588,10 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.22.0.tgz", - "integrity": "sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.23.0.tgz", + "integrity": "sha512-1sK4ILJbCmZOTt9k4vkoulT6/y5CHJ1qUYxqpF1K/DBAd8+ZUL4LlSCxOssuH5m4rUaaN0uS0HlVPvd45zjduQ==", "dev": true, - "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -1711,20 +1601,19 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.22.0.tgz", - "integrity": "sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.23.0.tgz", + "integrity": "sha512-LcqzfipsB8RTvH8FX24W4UUFk1bl+0yTOf9ZA08XngFwMg4Kj8A+9hwz8Cr/ZS4KwHrmo9PJiLZkOt49vPnuvQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.22.0", - "@typescript-eslint/visitor-keys": "8.22.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1742,7 +1631,6 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -1752,7 +1640,6 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -1764,11 +1651,10 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -1777,16 +1663,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.22.0.tgz", - "integrity": "sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.23.0.tgz", + "integrity": "sha512-uB/+PSo6Exu02b5ZEiVtmY6RVYO7YU5xqgzTIVZwTHvvK3HsL8tZZHFaTLFtRG3CsV4A5mhOv+NZx5BlhXPyIA==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.22.0", - "@typescript-eslint/types": "8.22.0", - "@typescript-eslint/typescript-estree": "8.22.0" + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/typescript-estree": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1801,13 +1686,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.22.0.tgz", - "integrity": "sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.23.0.tgz", + "integrity": "sha512-oWWhcWDLwDfu++BGTZcmXWqpwtkwb5o7fxUIGksMQQDSdPW9prsSnfIOZMlsj4vBOSrcnjIUZMiIjODgGosFhQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/types": "8.23.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -1823,7 +1707,6 @@ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==", "dev": true, - "license": "MIT", "dependencies": { "@babel/core": "^7.26.0", "@babel/plugin-transform-react-jsx-self": "^7.25.9", @@ -1843,7 +1726,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, - "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1856,7 +1738,6 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -1866,7 +1747,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1883,7 +1763,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -1898,22 +1777,34 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1924,7 +1815,6 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, - "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -1951,7 +1841,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -1970,15 +1859,14 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001695", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz", - "integrity": "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==", + "version": "1.0.30001697", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001697.tgz", + "integrity": "sha512-GwNPlWJin8E+d7Gxq96jxM6w0w+VFeyyXRsjU58emtkYqnbwHqXm5uT2uCmO0RQE9htWknOP4xtBlLmM/gWxvQ==", "dev": true, "funding": [ { @@ -1993,15 +1881,13 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ], - "license": "CC-BY-4.0" + ] }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2018,7 +1904,6 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -2030,29 +1915,44 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" + "dev": true + }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "engines": { + "node": ">=18" + } }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, - "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2066,15 +1966,13 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, - "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -2091,14 +1989,20 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" + "dev": true + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "license": "Apache-2.0", "bin": { "detect-libc": "bin/detect-libc.js" }, @@ -2107,17 +2011,15 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.88", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.88.tgz", - "integrity": "sha512-K3C2qf1o+bGzbilTDCTBhTQcMS9KW60yTAaTeeXsfvQuTDDwlokLam/AdqlqcSy9u4UainDgsHV23ksXAOgamw==", - "dev": true, - "license": "ISC" + "version": "1.5.92", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.92.tgz", + "integrity": "sha512-BeHgmNobs05N1HMmMZ7YIuHfYBGlq/UmvlsTgg+fsbFs9xVMj+xJHFg19GN04+9Q+r8Xnh9LXqaYIyEWElnNgQ==", + "dev": true }, "node_modules/enhanced-resolve": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz", - "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==", - "license": "MIT", + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -2131,7 +2033,6 @@ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", "hasInstallScript": true, - "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -2171,7 +2072,6 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -2181,7 +2081,6 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -2194,7 +2093,6 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", @@ -2254,7 +2152,6 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0.tgz", "integrity": "sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -2267,7 +2164,6 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.18.tgz", "integrity": "sha512-IRGEoFn3OKalm3hjfolEWGqoF/jPqeEYFp+C8B0WMzwGwBMvlRDQd06kghDhF0C61uJ6WfSDhEZE/sAQjduKgw==", "dev": true, - "license": "MIT", "peerDependencies": { "eslint": ">=8.40" } @@ -2277,7 +2173,6 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -2294,7 +2189,6 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -2307,7 +2201,6 @@ "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", @@ -2325,7 +2218,6 @@ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -2338,7 +2230,6 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -2351,7 +2242,6 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -2361,7 +2251,6 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -2370,15 +2259,13 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/fast-glob": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -2395,7 +2282,6 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -2407,22 +2293,19 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/fastq": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", - "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", + "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", "dev": true, - "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -2432,7 +2315,6 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, - "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, @@ -2445,7 +2327,6 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, - "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2458,7 +2339,6 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -2475,7 +2355,6 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, - "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" @@ -2488,15 +2367,45 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", - "dev": true, - "license": "ISC" + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, - "license": "MIT", "optional": true, "os": [ "darwin" @@ -2510,7 +2419,6 @@ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -2520,7 +2428,6 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -2533,7 +2440,6 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -2544,22 +2450,19 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -2569,17 +2472,15 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, - "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, - "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -2596,7 +2497,6 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -2606,7 +2506,6 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2616,7 +2515,6 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, - "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -2629,7 +2527,6 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -2638,14 +2535,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" + "dev": true }, "node_modules/jiti": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", - "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" } @@ -2653,15 +2548,13 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -2674,7 +2567,6 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, - "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -2686,29 +2578,25 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, - "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -2721,7 +2609,6 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -2731,7 +2618,6 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -2744,7 +2630,6 @@ "version": "1.29.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.1.tgz", "integrity": "sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q==", - "license": "MPL-2.0", "dependencies": { "detect-libc": "^1.0.3" }, @@ -2775,7 +2660,6 @@ "cpu": [ "arm64" ], - "license": "MPL-2.0", "optional": true, "os": [ "darwin" @@ -2795,7 +2679,6 @@ "cpu": [ "x64" ], - "license": "MPL-2.0", "optional": true, "os": [ "darwin" @@ -2815,7 +2698,6 @@ "cpu": [ "x64" ], - "license": "MPL-2.0", "optional": true, "os": [ "freebsd" @@ -2835,7 +2717,6 @@ "cpu": [ "arm" ], - "license": "MPL-2.0", "optional": true, "os": [ "linux" @@ -2855,7 +2736,6 @@ "cpu": [ "arm64" ], - "license": "MPL-2.0", "optional": true, "os": [ "linux" @@ -2875,7 +2755,6 @@ "cpu": [ "arm64" ], - "license": "MPL-2.0", "optional": true, "os": [ "linux" @@ -2895,7 +2774,6 @@ "cpu": [ "x64" ], - "license": "MPL-2.0", "optional": true, "os": [ "linux" @@ -2915,7 +2793,6 @@ "cpu": [ "x64" ], - "license": "MPL-2.0", "optional": true, "os": [ "linux" @@ -2935,7 +2812,6 @@ "cpu": [ "arm64" ], - "license": "MPL-2.0", "optional": true, "os": [ "win32" @@ -2955,7 +2831,6 @@ "cpu": [ "x64" ], - "license": "MPL-2.0", "optional": true, "os": [ "win32" @@ -2973,7 +2848,6 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -2988,14 +2862,12 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -3008,7 +2880,6 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "license": "ISC", "dependencies": { "yallist": "^3.0.2" } @@ -3018,7 +2889,6 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 8" } @@ -3028,7 +2898,6 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, - "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -3037,12 +2906,30 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3054,8 +2941,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/nanoid": { "version": "3.3.8", @@ -3067,7 +2953,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -3079,22 +2964,19 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, - "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -3112,7 +2994,6 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -3128,7 +3009,6 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -3144,7 +3024,6 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -3157,7 +3036,6 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -3167,7 +3045,6 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -3175,15 +3052,13 @@ "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.6" }, @@ -3209,7 +3084,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", @@ -3224,17 +3098,20 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.8.0" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -3257,14 +3134,12 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" }, @@ -3276,7 +3151,6 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -3290,18 +3164,16 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/react-router": { - "version": "6.28.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.2.tgz", - "integrity": "sha512-BgFY7+wEGVjHCiqaj2XiUBQ1kkzfg6UoKYwEe0wv+FF+HNPCxtS/MVPvLAPH++EsuCMReZl9RYVGqcHLk5ms3A==", - "license": "MIT", + "version": "6.29.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.29.0.tgz", + "integrity": "sha512-DXZJoE0q+KyeVw75Ck6GkPxFak63C4fGqZGNijnWgzB/HzSP1ZfTlBj5COaGWwhrMQ/R8bXiq5Ooy4KG+ReyjQ==", "dependencies": { - "@remix-run/router": "1.21.1" + "@remix-run/router": "1.22.0" }, "engines": { "node": ">=14.0.0" @@ -3310,12 +3182,49 @@ "react": ">=16.8" } }, + "node_modules/react-router-dom": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.1.5.tgz", + "integrity": "sha512-/4f9+up0Qv92D3bB8iN5P1s3oHAepSGa9h5k6tpTFlixTTskJZwKGhJ6vRJ277tLD1zuaZTt95hyGWV1Z37csQ==", + "dependencies": { + "react-router": "7.1.5" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/react-router-dom/node_modules/react-router": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.5.tgz", + "integrity": "sha512-8BUF+hZEU4/z/JD201yK6S+UYhsf58bzYIDq2NS1iGpwxSXDu7F+DeGSkIXMFBuHZB21FSiCzEcUb18cQNdRkA==", + "dependencies": { + "@types/cookie": "^0.6.0", + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0", + "turbo-stream": "2.4.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -3325,17 +3234,15 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, "node_modules/rollup": { - "version": "4.32.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.32.0.tgz", - "integrity": "sha512-JmrhfQR31Q4AuNBjjAX4s+a/Pu/Q8Q9iwjWBsjRH1q52SPFE2NqRMK6fUZKKnvKO6id+h7JIRf0oYsph53eATg==", - "license": "MIT", + "version": "4.34.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.4.tgz", + "integrity": "sha512-spF66xoyD7rz3o08sHP7wogp1gZ6itSq22SGa/IZTcUDXDlOyrShwMwkVSB+BUxFRZZCUYqdb3KWDEOMVQZxuw==", "dependencies": { "@types/estree": "1.0.6" }, @@ -3347,25 +3254,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.32.0", - "@rollup/rollup-android-arm64": "4.32.0", - "@rollup/rollup-darwin-arm64": "4.32.0", - "@rollup/rollup-darwin-x64": "4.32.0", - "@rollup/rollup-freebsd-arm64": "4.32.0", - "@rollup/rollup-freebsd-x64": "4.32.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.32.0", - "@rollup/rollup-linux-arm-musleabihf": "4.32.0", - "@rollup/rollup-linux-arm64-gnu": "4.32.0", - "@rollup/rollup-linux-arm64-musl": "4.32.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.32.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.32.0", - "@rollup/rollup-linux-riscv64-gnu": "4.32.0", - "@rollup/rollup-linux-s390x-gnu": "4.32.0", - "@rollup/rollup-linux-x64-gnu": "4.32.0", - "@rollup/rollup-linux-x64-musl": "4.32.0", - "@rollup/rollup-win32-arm64-msvc": "4.32.0", - "@rollup/rollup-win32-ia32-msvc": "4.32.0", - "@rollup/rollup-win32-x64-msvc": "4.32.0", + "@rollup/rollup-android-arm-eabi": "4.34.4", + "@rollup/rollup-android-arm64": "4.34.4", + "@rollup/rollup-darwin-arm64": "4.34.4", + "@rollup/rollup-darwin-x64": "4.34.4", + "@rollup/rollup-freebsd-arm64": "4.34.4", + "@rollup/rollup-freebsd-x64": "4.34.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.4", + "@rollup/rollup-linux-arm-musleabihf": "4.34.4", + "@rollup/rollup-linux-arm64-gnu": "4.34.4", + "@rollup/rollup-linux-arm64-musl": "4.34.4", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.4", + "@rollup/rollup-linux-riscv64-gnu": "4.34.4", + "@rollup/rollup-linux-s390x-gnu": "4.34.4", + "@rollup/rollup-linux-x64-gnu": "4.34.4", + "@rollup/rollup-linux-x64-musl": "4.34.4", + "@rollup/rollup-win32-arm64-msvc": "4.34.4", + "@rollup/rollup-win32-ia32-msvc": "4.34.4", + "@rollup/rollup-win32-x64-msvc": "4.34.4", "fsevents": "~2.3.2" } }, @@ -3388,7 +3295,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -3397,7 +3303,6 @@ "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" } @@ -3407,17 +3312,20 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -3430,7 +3338,6 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -3439,7 +3346,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -3449,7 +3355,6 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" }, @@ -3462,7 +3367,6 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -3471,16 +3375,14 @@ } }, "node_modules/tailwindcss": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.0.tgz", - "integrity": "sha512-ULRPI3A+e39T7pSaf1xoi58AqqJxVCLg8F/uM5A3FadUbnyDTgltVnXJvdkTjwCOGA6NazqHVcwPJC5h2vRYVQ==", - "license": "MIT" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.3.tgz", + "integrity": "sha512-ImmZF0Lon5RrQpsEAKGxRvHwCvMgSC4XVlFRqmbzTEDb/3wvin9zfEZrMwgsa3yqBbPqahYcVI6lulM2S7IZAA==" }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "license": "MIT", "engines": { "node": ">=6" } @@ -3490,7 +3392,6 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -3499,11 +3400,10 @@ } }, "node_modules/ts-api-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", - "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", + "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", "dev": true, - "license": "MIT", "engines": { "node": ">=18.12" }, @@ -3511,12 +3411,16 @@ "typescript": ">=4.8.4" } }, + "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==" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -3529,7 +3433,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3539,15 +3442,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.22.0.tgz", - "integrity": "sha512-Y2rj210FW1Wb6TWXzQc5+P+EWI9/zdS57hLEc0gnyuvdzWo8+Y8brKlbj0muejonhMI/xAZCnZZwjbIfv1CkOw==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.23.0.tgz", + "integrity": "sha512-/LBRo3HrXr5LxmrdYSOCvoAMm7p2jNizNfbIpCgvG4HMsnoprRUOce/+8VJ9BDYWW68rqIENE/haVLWPeFZBVQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.22.0", - "@typescript-eslint/parser": "8.22.0", - "@typescript-eslint/utils": "8.22.0" + "@typescript-eslint/eslint-plugin": "8.23.0", + "@typescript-eslint/parser": "8.23.0", + "@typescript-eslint/utils": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3565,8 +3467,7 @@ "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" + "devOptional": true }, "node_modules/update-browserslist-db": { "version": "1.1.2", @@ -3587,7 +3488,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" @@ -3604,20 +3504,18 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, "node_modules/vite": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", - "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", - "license": "MIT", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz", + "integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==", "dependencies": { "esbuild": "^0.24.2", - "postcss": "^8.4.49", - "rollup": "^4.23.0" + "postcss": "^8.5.1", + "rollup": "^4.30.1" }, "bin": { "vite": "bin/vite.js" @@ -3685,7 +3583,6 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -3701,7 +3598,6 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3710,15 +3606,13 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" + "dev": true }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, From cf7e3c13eea0d5018d5491b8fa39872f9e671ca8 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Fri, 14 Feb 2025 21:03:05 -0500 Subject: [PATCH 13/18] reduce folder scope --- .../handlers/file-manager/file-structure/prompt.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts b/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts index 3bb1ab72..93af4737 100644 --- a/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts +++ b/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts @@ -61,15 +61,10 @@ Additional Rules: case 'frontend': roleDescription = 'an expert frontend developer'; includeSections = ` - Folder Structure: + Folder Structure example: src: Main source code folder. - components: Reusable UI elements grouped by category (e.g., common, layout, specific). - contexts: Global state management (e.g., auth, theme, player). - hooks: Custom hooks for data fetching and state management. - pages: Route-specific views (e.g., Home, Search, Playlist). - utils: Utility functions (e.g., constants, helpers, validators). - apis: Organized API logic (e.g., auth, music, user). - router.ts: Central routing configuration. + pages: Route-specific views. For Example: Home, Search, Playlist. + router.tsx: Central routing configuration. index.tsx: Application entry point. `; excludeSections = ` @@ -81,6 +76,7 @@ Additional Rules: `; fileNamingGuidelines = ` File and Folder Naming Guidelines: + Must use .tsx extension for all files. Use meaningful and descriptive file names. Do NOT use page_view_* and global_view_* prefixes for folder or file names. For components, include an index.tsx file in each folder to simplify imports. From c88df24dcef0fa603dc3af85ea62ebe5a1c99349 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Fri, 14 Feb 2025 21:04:46 -0500 Subject: [PATCH 14/18] fix error --- backend/src/build-system/utils/file_generator_util.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/build-system/utils/file_generator_util.ts b/backend/src/build-system/utils/file_generator_util.ts index d6d6f1af..0d40d157 100644 --- a/backend/src/build-system/utils/file_generator_util.ts +++ b/backend/src/build-system/utils/file_generator_util.ts @@ -4,6 +4,7 @@ import { Logger } from '@nestjs/common'; import { VirtualDirectory } from '../virtual-dir'; import { extractJsonFromMarkdown } from 'src/build-system/utils/strings'; import toposort from 'toposort'; +import { RetryableError } from '../errors'; interface FileDependencyInfo { filePath: string; @@ -295,7 +296,7 @@ function buildConcurrencyLayers( // 4. If there are any files left with in-degree > 0, there's a cycle const unprocessed = Object.entries(inDegree).filter(([_, deg]) => deg > 0); if (unprocessed.length > 0) { - throw new Error( + throw new RetryableError( `Cycle or leftover dependencies detected for: ${unprocessed .map(([f]) => f) .join(', ')}`, From 64782b44fadbd75654397b2ede290164f7895cc1 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Sun, 16 Feb 2025 11:15:01 -0500 Subject: [PATCH 15/18] update file fix and frontend generate --- .../file-manager/file-structure/prompt.ts | 1 + .../FileOperationManager.ts | 8 +- .../FixResponseParser.ts | 49 ++-- .../FrontendQueueProcessor.ts | 26 ++- .../handlers/frontend-code-generate/index.ts | 12 +- .../handlers/frontend-code-generate/prompt.ts | 217 ++++++------------ backend/template/react-ts/tsconfig.app.json | 4 +- backend/template/react-ts/tsconfig.json | 6 +- backend/template/react-ts/tsconfig.node.json | 4 +- 9 files changed, 131 insertions(+), 196 deletions(-) diff --git a/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts b/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts index 93af4737..10c75286 100644 --- a/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts +++ b/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts @@ -63,6 +63,7 @@ Additional Rules: includeSections = ` Folder Structure example: src: Main source code folder. + contexts: Global state management. pages: Route-specific views. For Example: Home, Search, Playlist. router.tsx: Central routing configuration. index.tsx: Application entry point. diff --git a/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts index 7f0981aa..1d1de52a 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts @@ -1,12 +1,14 @@ import { Logger } from '@nestjs/common'; import { writeFile, rename, readFile } from 'fs/promises'; import path from 'path'; +import { removeCodeBlockFences } from 'src/build-system/utils/strings'; export interface FileOperation { action: 'write' | 'rename' | 'read'; originalPath?: string; renamePath?: string; code?: string; + paths?: string[]; } export class FileOperationManager { @@ -51,8 +53,7 @@ export class FileOperationManager { } break; case 'read': - await this.handleRead(op); - newFilePath = op.renamePath || null; + // await this.handleRead(op); break; } } catch (error) { @@ -71,7 +72,8 @@ export class FileOperationManager { this.safetyChecks(originalPath); this.logger.debug('start update file to: ' + originalPath); - await writeFile(originalPath, op.code, 'utf-8'); + const parseCode = removeCodeBlockFences(op.code); + await writeFile(originalPath, parseCode, 'utf-8'); } private async handleRead(op: FileOperation): Promise { diff --git a/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts b/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts index 8469856e..eced7371 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts @@ -15,34 +15,33 @@ export class FixResponseParser { throw new Error('Invalid JSON format'); } - if (!parsedData.fix || !parsedData.fix.operations) { + if (!parsedData.fix || !parsedData.fix.operation) { throw new Error("Invalid JSON structure: Missing 'fix.operations'"); } - const operations: FileOperation[] = parsedData.fix.operations - .map((op: any) => { - if (op.type === 'WRITE') { - return { - action: 'write', - originalPath: filePath, - code: parsedData.fix.generate?.trim(), - }; - } else if (op.type === 'RENAME') { - return { - action: 'rename', - originalPath: op.original_path, - renamePath: op.path, - code: parsedData.fix.generate?.trim(), - }; - } else if (op.type === 'READ') { - return { - action: 'read', - originalPath: op.original_path, - }; - } - return null; - }) - .filter(Boolean); + const op = parsedData.fix.operation; + const operations: FileOperation[] = []; + + if (op.type === 'WRITE') { + operations.push({ + action: 'write', + originalPath: filePath, + code: op.content?.trim(), + }); + } else if (op.type === 'RENAME') { + operations.push({ + action: 'rename', + originalPath: op.original_path, + renamePath: op.path, + }); + } else if (op.type === 'READ' && Array.isArray(op.paths)) { + for (const path of op.paths) { + operations.push({ + action: 'read', + originalPath: path, + }); + } + } // this.logger.log('Extracted operations:', operations); return operations; diff --git a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts index 9d8fc6b9..a11b77e5 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts @@ -135,7 +135,7 @@ export class FrontendQueueProcessor { this.logger.debug('raw error: ' + rawErrorText); - const fixPrompt = generateFileOperationPrompt(); + const fixPrompt = generateFileOperationPrompt(task.filePath); const commonIssuePrompt = generateCommonErrorPrompt(); const fileOperationManager = new FileOperationManager( @@ -168,17 +168,22 @@ export class FrontendQueueProcessor { }, { role: 'user', - content: `## Overview of The Dependencies file you may need: \n ${task.dependenciesPath}`, + content: `## Overview of The Internal Dependencies file you may need: \n ${task.dependenciesPath}`, }, { role: 'assistant', content: `Let me analysis the current file. Why error message occour? - Let me check some common issue to make sure my thinking is correct ${commonIssuePrompt}.`, + Let me check some common issue to make sure my thinking is correct ${commonIssuePrompt}. + I must follow the output format`, }, { role: 'user', content: `Now you should start fix the current code error.`, }, + { + role: 'assistant', + content: `Let me check my result and I must follow the output format`, + }, ], }, 'fix code (generic)', @@ -222,7 +227,7 @@ export class FrontendQueueProcessor { { role: 'system', content: fixPrompt }, { role: 'user', - content: ` ## Current file: \n ${task.filePath} ## Current Code \n ${originalContent}\n `, + content: `## Current Code \n ${originalContent}\n `, }, { role: 'user', @@ -231,12 +236,12 @@ export class FrontendQueueProcessor { { role: 'assistant', content: - "Good, now provider your dependencies, it's okay dependencies are empty, which means you don't have any dependencies", + "Good, now provider your Internal dependencies, it's okay dependencies are empty, which means you don't have any dependencies", }, { role: 'user', - content: `## Overview of The Dependencies files: \n ${task.dependenciesPath}\n - # Additional imported files:\n ${operations + content: `## Overview of Internal Dependencies files: \n ${task.dependenciesPath}\n + ## Internal Dependencies files content:\n ${operations .filter((op) => op.action === 'read' && op.code) .map((op) => `File: ${op.originalPath}\nContent:\n${op.code}`) .join('\n\n')}`, @@ -245,12 +250,17 @@ export class FrontendQueueProcessor { role: 'assistant', content: `Let me analysis the current file. Why error message occour This time I shouldn't use the read tool because previous context already use it. - Let me check some common issue to make sure my thinking is correct ${commonIssuePrompt}.`, + Let me check some common issue to make sure my thinking is correct ${commonIssuePrompt}. + I must follow the output format`, }, { role: 'user', content: `Now you should start fix the current code error.`, }, + { + role: 'assistant', + content: `Let me check my result and I must follow the output format`, + }, ], }, 'fix code (generic)', diff --git a/backend/src/build-system/handlers/frontend-code-generate/index.ts b/backend/src/build-system/handlers/frontend-code-generate/index.ts index b5f152c6..e39b40a0 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/index.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/index.ts @@ -117,6 +117,14 @@ export class FrontendCodeHandler implements BuildHandler { path.resolve(frontendPath, file), ); + // Ensure fileInfos[file] exists before modifying + if (!fileInfos[file]) { + fileInfos[file] = { + filePath: file, // Assuming `file` is the correct path + dependsOn: [], + }; + } + // Gather direct dependencies let directDepsArray = fileInfos[file]?.dependsOn || []; @@ -296,10 +304,10 @@ export class FrontendCodeHandler implements BuildHandler { role: 'user' as const, content: ` - ## Overview of The Dependencies file you may need + ## Overview of The Internal Dependencies filess you may need ${directDepsPathString} - ## Detail about each Dependencies: + ## Detail about each Internal Dependencies: ${dependenciesText}\n `, }, diff --git a/backend/src/build-system/handlers/frontend-code-generate/prompt.ts b/backend/src/build-system/handlers/frontend-code-generate/prompt.ts index 543e605c..5508ac20 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/prompt.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/prompt.ts @@ -2,61 +2,37 @@ export const generateFrontEndCodePrompt = ( currentFile: string, dependencyFilePath: string, ): string => { - return `You are an expert frontend developer specializing in building scalable, maintainable, and production-ready React applications using TypeScript. - Your task: Generate complete and functional React frontend code based on the provided inputs. The output must include all essential files, folders, and logic for UI components, API integration, routing, and state management. + return `Role: You are an expert frontend developer specializing in building scalable, maintainable, and production-ready React applications using TypeScript. + Task: Generate complete, type-safe, and maintainable React code. Current File: ${currentFile}. - ### Instructions and Rules: - File Requirements: - Implement all specifications defined in the sitemap and UX datamap documents. - Ensure that the code includes necessary imports, state management, interactions, and API integrations without placeholders. - Incorporate hooks, APIs, or context based on dependencies provide - Use inline Tailwind CSS classes in TSX for all styling requirements. Avoid external .css files unless explicitly required by third-party libraries. - For src/index.tsx, ensure it imports index.css for global styles or third-party integrations. - - Code Standards: - Use React functional components and modern hooks (e.g., useState, useEffect, useContext). - Adhere to styling guidelines (e.g., Tailwind CSS, CSS Modules) as described in dependency files. - Use descriptive and meaningful names for all variables, functions, and components. - Follow accessibility best practices, including proper aria attributes. - When need to import from dependency file, use the user provide dependency file path. - Do not include any unnecessary or redundant code. - Do not assume any specific backend or API implementation. - Do not asume any import or dependencies. - Use only the dependencies provided below for imports. Ensure these imports are included correctly in the generated code wherever applicable. - - ### Dependencies: - Below are the required dependency files to be included in the generated code. - - - File path: (dependency file code path) - - \`\`\`typescript - dependency file content - \`\`\` - - - - Comments: - Add comments for each major code block or function, describing its purpose and logic. - Mark placeholders or sections where additional future integrations might be needed. - - Error Handling: - Handle edge cases such as loading states, error states, and empty data gracefully. - Include fallback UI components or error boundaries where applicable. - - Output Completeness: - The generated file must be production-ready and include all necessary imports and dependencies. - This final result must be 100% complete. Will be directly use in the production - - ### Output Format: - DO NOT include any code fences (no \`\`\`). + # Instructions and Rules: + 1. Implement Only One file: Implement only the given file. + 2. COMPLETE CODE: Your code will be part of the entire project, so please implement complete, reliable, reusable code snippets. + 3. Type Safe: Follow typscript standard. + 4. Follow design: DONT CHANGE ANY DESIGN IN Document. + 5. CAREFULLY CHECK: + Before importing a file, verify its existence. + THAT YOU DONT MISSED ANY Internal Dependencies import. + If missing, suggest an alternative or define mock data. + 6. Before using a external variable/module, make sure you import it first. + 7. Error Handling: Implement proper error handling in API calls and interactions with external modules. + 8. Code Standards: Adhere to styling guidelines (e.g., Tailwind CSS, CSS Modules), and Use only Tailwind UI for styling, applying all styles via inline class names (className). + 9. Mock the response: if the API returns an empty or undefined value. + 10. Write EVERY CODE DETAIL, DON'T LEAVE TODO. + + ## Library: + "react-router": "^6", + "react": "^18", + "@tailwindcss/vite": "^4.0.0" + + + ## Output Format: Output your final code wrapped in tags ONLY, like: ...full code... - `; }; @@ -140,45 +116,41 @@ Please fix the code so it compiles successfully. Return only the updated code wr `; } -export function generateFileOperationPrompt(): string { +export function generateFileOperationPrompt(currentFile: string): string { return ` - You are a senior developer fixing a TypeScript project. Analyze the error and choose appropriate file operations. Return a structured JSON object that contains the fix. + Role: You are a code-fixing assistant expert at typescript. + Task: Based on the given error, generate the appropriate fix operation. + Current File: ${currentFile}. -Available Tools: +Available operations: 1. WRITE - Modify/create files 2. RENAME - RENAME the file 3. READ - Read the file -**Instructions:** -1. **Understand the error from \`error\`** and determine what's wrong. -2. **Analyze the dependencies** in \`dependencies file path\` to ensure type compatibility. -3. **Modify the original code** in \`Current file Code\` while preserving its logic. -4. **Ensure TypeScript type safety** and fix any possible runtime issues. -5. Error Analysis: - - Read the error message carefully - - Identify error type (compilation/runtime/naming) - - Check if error originates from current file or dependencies - -6. Dependency Check: +## Instructions: +1. Use only one operation. +2. Fix Only One file: Fix only the given file. +3. Fix every error: Try Fix every error in the given file. +4. Ask your self: + why the errors occur? + which lines of code are causing errors? +5. Internal Dependency Check: - Compare types/interfaces with dependencies file path provide by user. - Ensure all imports match actual exports - Verify type signatures align - -7. Modification Rules: +6. Modification Rules: - Preserve original functionality - Maintain TypeScript strict mode compliance - Keep existing code style/conventions - Add type guards where necessary - Prefer generics over 'any' -8. File Operations: - - Use RENAME only for extension issues (e.g., .js → .tsx) +7. File Operations: + - Use RENAME only for extension issues (e.g., .ts → .tsx) - Use WRITE for code/content changes - Use READ for not enough information so solve the issue -9. When User provide "Additional imported files" use this as to help you fix the error. Remeber only write other files code to current file when it is necessary - -10. generate must include full code. +8. Content must include full code. **Common Errors & Fixes** @@ -186,81 +158,42 @@ Available Tools: TypeScript type error → Use the WRITE tool. Not assignable to parameter of type → Use the READ tool if you dont have enough information to fix. -**safety check** -1. Never delete files outside /src directory -3. Maintain existing export patterns -4. Verify all type references after changes - **Output format:** -Respond format in this json format: - -{ - "fix": { - "operations": [ - { - "type": "WRITE" - }, - { - "type": "RENAME", - "path": "src/new/path/here.tsx", - "original_path": "src/old/path/here.ts" - } - { - "type": "READ", - "original_path": "src/the/path/read.tsx" - } - ], - "generate": " Code here " - } -} - - +To keep the structure consistent, other operations remain single-action: -**Good Tool using Example:** -Example Good WRITE Operation: +1. Read File +If you need to inspect the file before fixing it: { "fix": { - "operations": [ - { - "type": "WRITE" - } - ], - "generate": " Code here " + "operation": { + "type": "READ", + "paths": ["src/path/to/file1.tsx", "src/path/to/file2.ts"] + } } } -Example Good RENAME Operation: +2. Writing a Single File +If you found an issue and are generating a fix: { "fix": { - "operations": [ - { - "type": "RENAME", - "path": "src/utils/helpers.tsx", - "original_path": "src/utils/helpers.js" - } - ], - "generate": "" + "operation": { + "type": "WRITE", + "content": "Fixed code here" + } } } -Example Good READ Operation: +Renaming a Single File: +If a file needs to be renamed: { "fix": { - "operations": [ - { - "type": "READ", - "original_path": "src/utils/helpers.tsx", - } - ... You can ask to read more then one file. - ], - "generate": "" + "operation": { + "type": "RENAME", + "path": "src/new/path/here.tsx", + "original_path": "src/old/path/here.ts" + } } } - -**Important Note** -1.The output must be complete and strictly formatted. -2.DO NOT EXPLAIN OUTSIDE JSON. - `; } @@ -276,17 +209,6 @@ Fix: Rename .ts to .tsx since JSX syntax requires TypeScript support. -✅ Correct Fix Output: - - - - - src/components/Button.ts - - - - - 2. defined but never used Issue -> Use the WRITE Tool Error example: @@ -295,26 +217,15 @@ Error example: Fix: Remove the defined but never used component from the import. -✅ Correct Fix Output: - { - "fix": { - "operations": [ - { - "type": "WRITE" - } - ], - "generate": "Do the fix for the import and other part stay the same and put Full code here!" - } - } - 3. Import error -> Use the WRITE Tool Error example: - Cannot find module './components/GlobalFooter' or its corresponding type declarations. + Cannot find module 'react-hook-form' or its corresponding type declarations. Fix: - Read carefully about previous "dependency file Paths" use the path in the fix if applicable. + 1. Read carefully about previous "Internal dependency file Paths" use the path in the fix if applicable. + 2. if Internal dependency file didnt mention this then remove the import. `; } diff --git a/backend/template/react-ts/tsconfig.app.json b/backend/template/react-ts/tsconfig.app.json index 6beede0b..ac017979 100644 --- a/backend/template/react-ts/tsconfig.app.json +++ b/backend/template/react-ts/tsconfig.app.json @@ -16,8 +16,8 @@ "noEmit": true, "jsx": "react-jsx", "strict": false, - "noUnusedLocals": true, - "noUnusedParameters": true, + "noUnusedLocals": false, + "noUnusedParameters": false, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true }, diff --git a/backend/template/react-ts/tsconfig.json b/backend/template/react-ts/tsconfig.json index 1ffef600..ce956f3d 100644 --- a/backend/template/react-ts/tsconfig.json +++ b/backend/template/react-ts/tsconfig.json @@ -3,5 +3,9 @@ "references": [ { "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" } - ] + ], + "compilerOptions": { + "noUnusedLocals": false, + "noUnusedParameters": false + } } diff --git a/backend/template/react-ts/tsconfig.node.json b/backend/template/react-ts/tsconfig.node.json index b6da3843..5a69465d 100644 --- a/backend/template/react-ts/tsconfig.node.json +++ b/backend/template/react-ts/tsconfig.node.json @@ -15,8 +15,8 @@ /* Linting */ "strict": false, - "noUnusedLocals": true, - "noUnusedParameters": true, + "noUnusedLocals": false, + "noUnusedParameters": false, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true }, From 373f11c6d1d1bd0d0c1be407ed08da62edca262d Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Sun, 16 Feb 2025 11:15:47 -0500 Subject: [PATCH 16/18] update test case --- backend/src/build-system/__tests__/fullstack-gen.spec.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/src/build-system/__tests__/fullstack-gen.spec.ts b/backend/src/build-system/__tests__/fullstack-gen.spec.ts index 395bcdaa..846b3b06 100644 --- a/backend/src/build-system/__tests__/fullstack-gen.spec.ts +++ b/backend/src/build-system/__tests__/fullstack-gen.spec.ts @@ -21,8 +21,9 @@ import { FrontendCodeHandler } from '../handlers/frontend-code-generate'; const sequence: BuildSequence = { id: 'test-backend-sequence', version: '1.0.0', - name: 'Spotify-like Music Web', - description: 'Users can play music', + name: 'Wrtie a Cool personal website', + description: + 'A personal blog website. I am a cybersecurity engineer so i want it to show i am a really cool hacker', databaseType: 'SQLite', nodes: [ { From 62015a578027bdbfaa0cb228a29b1d1795267f2b Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Sun, 16 Feb 2025 20:56:21 -0500 Subject: [PATCH 17/18] refect code structure and add comment --- .../frontend-code-generate/CodeTaskQueue.ts | 21 --- ...ntendCodeValidator.ts => CodeValidator.ts} | 11 +- .../FileOperationManager.ts | 121 +++++++++++++++++- .../FixResponseParser.ts | 49 ------- .../FrontendQueueProcessor.ts | 79 ++++++++++-- .../handlers/frontend-code-generate/index.ts | 8 +- 6 files changed, 196 insertions(+), 93 deletions(-) delete mode 100644 backend/src/build-system/handlers/frontend-code-generate/CodeTaskQueue.ts rename backend/src/build-system/handlers/frontend-code-generate/{FrontendCodeValidator.ts => CodeValidator.ts} (91%) delete mode 100644 backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts diff --git a/backend/src/build-system/handlers/frontend-code-generate/CodeTaskQueue.ts b/backend/src/build-system/handlers/frontend-code-generate/CodeTaskQueue.ts deleted file mode 100644 index 1b6e6ad5..00000000 --- a/backend/src/build-system/handlers/frontend-code-generate/CodeTaskQueue.ts +++ /dev/null @@ -1,21 +0,0 @@ -export interface FileTask { - filePath: string; // e.g. "src/components/MyComponent.ts" - fileContents: string; // the code you got from the LLM - dependenciesPath?: string; -} - -export class CodeTaskQueue { - private tasks: FileTask[] = []; - - enqueue(task: FileTask) { - this.tasks.push(task); - } - - dequeue(): FileTask | undefined { - return this.tasks.shift(); - } - - get size(): number { - return this.tasks.length; - } -} diff --git a/backend/src/build-system/handlers/frontend-code-generate/FrontendCodeValidator.ts b/backend/src/build-system/handlers/frontend-code-generate/CodeValidator.ts similarity index 91% rename from backend/src/build-system/handlers/frontend-code-generate/FrontendCodeValidator.ts rename to backend/src/build-system/handlers/frontend-code-generate/CodeValidator.ts index 761b9247..bdea580b 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FrontendCodeValidator.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/CodeValidator.ts @@ -42,24 +42,22 @@ export class FrontendCodeValidator { npmProcess.stdout.on('data', (data: Buffer) => { const output = data.toString(); stdoutBuffer += output; - // this.logger.log(output); }); npmProcess.stderr.on('data', (data: Buffer) => { const output = data.toString(); stderrBuffer += output; - // this.logger.log(output); }); npmProcess.on('close', (code: number) => { if (code !== 0) { // Build failed – use stderr if available, else fallback to stdout. const errorMessage = stderrBuffer || stdoutBuffer; - // this.logger.error( - // `Build process exited with code ${code}. Error: ${errorMessage}`, - // ); + this.logger.verbose( + `Build process exited with code ${code}. Error: ${errorMessage}`, + ); - this.logger.error(`Build process exited with code ${code}.`); + // this.logger.error(`Build process exited with code ${code}.`); resolve({ success: false, error: errorMessage, @@ -74,7 +72,6 @@ export class FrontendCodeValidator { }); npmProcess.on('error', (err: Error) => { - this.logger.error('Failed to run npm build command:', err); reject(err); }); }); diff --git a/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts index 1d1de52a..3a536e2f 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FileOperationManager.ts @@ -1,3 +1,15 @@ +/** + * FileOperationManager.ts + * + * This file defines: + * 1) An interface `FileOperation` to describe + * how a file operation request should look. + * 2) A class `FileOperationManager` that implements + * the logic for performing write, rename, and + * read operations on files, with safety checks + * to prevent unauthorized or dangerous file access. + */ + import { Logger } from '@nestjs/common'; import { writeFile, rename, readFile } from 'fs/promises'; import path from 'path'; @@ -11,6 +23,11 @@ export interface FileOperation { paths?: string[]; } +/** + * Manages file operations such as 'write', 'rename', and 'read'. + * parses JSON input to extract operations. + * Also enforces safety checks to prevent unauthorized access or edits. + */ export class FileOperationManager { private readonly projectRoot: string; private readonly allowedPaths: string[]; @@ -24,12 +41,13 @@ export class FileOperationManager { this.allowedPaths = [this.projectRoot]; } - private operationCount = 0; + /** + * Executes an array of file operations sequentially. + * + * @param operations - An array of operations to perform. + * @returns The final "renamePath" if any file was renamed, or null otherwise. + */ async executeOperations(operations: FileOperation[]): Promise { - // if (operations.length > 5) { - // throw new Error('Maximum 5 operations per fix'); - // } - let newFilePath: string | null = null; for (const op of operations) { @@ -53,6 +71,7 @@ export class FileOperationManager { } break; case 'read': + // We could implement a read action here if needed. // await this.handleRead(op); break; } @@ -67,6 +86,11 @@ export class FileOperationManager { return newFilePath; } + /** + * Handles the 'write' action: writes the given code string to the file. + * + * @param op - A FileOperation containing `originalPath` and `code`. + */ private async handleWrite(op: FileOperation): Promise { const originalPath = path.resolve(this.projectRoot, op.originalPath); this.safetyChecks(originalPath); @@ -76,6 +100,12 @@ export class FileOperationManager { await writeFile(originalPath, parseCode, 'utf-8'); } + /** + * Handles the 'read' action: reads a file from disk. + * + * @param op - A FileOperation containing `originalPath`. + * @returns The file content as a string, or null if it fails to read. + */ private async handleRead(op: FileOperation): Promise { try { const originalPath = path.resolve(this.projectRoot, op.originalPath); @@ -97,6 +127,11 @@ export class FileOperationManager { } } + /** + * Handles the 'rename' action: moves or renames a file. + * + * @param op - A FileOperation containing `originalPath` and `renamePath`. + */ private async handleRename(op: FileOperation): Promise { const originalPath = path.resolve(this.projectRoot, op.originalPath); const RenamePath = path.resolve(this.projectRoot, op.renamePath); @@ -110,6 +145,75 @@ export class FileOperationManager { await rename(originalPath, RenamePath); } + /** + * Parses JSON output (e.g., from an LLM) to build an array of FileOperations. + * This is often used when GPT provides structured instructions to + * read/write/rename files. + * + * input example: + * { + * "fix": { + * "operation": { + * "type": "READ", + * "paths": ["src/path/to/file1.tsx", "src/path/to/file2.ts"] + * } + * } + * } + * + * @param json - The JSON string containing the fix/operation details. + * @param filePath - The path of the file we’re primarily fixing (if any). + * @returns An array of FileOperation objects. + */ + parse(json: string, filePath: string): FileOperation[] { + this.logger.log('Parsing JSON:', json); + + let parsedData; + try { + parsedData = JSON.parse(json); + } catch (error) { + this.logger.error('Error parsing JSON:', error); + throw new Error('Invalid JSON format'); + } + + if (!parsedData.fix || !parsedData.fix.operation) { + throw new Error("Invalid JSON structure: Missing 'fix.operations'"); + } + + const op = parsedData.fix.operation; + const operations: FileOperation[] = []; + + if (op.type === 'WRITE') { + operations.push({ + action: 'write', + originalPath: filePath, + code: op.content?.trim(), + }); + } else if (op.type === 'RENAME') { + operations.push({ + action: 'rename', + originalPath: op.original_path, + renamePath: op.path, + }); + } else if (op.type === 'READ' && Array.isArray(op.paths)) { + for (const path of op.paths) { + operations.push({ + action: 'read', + originalPath: path, + }); + } + } + + // this.logger.log('Extracted operations:', operations); + return operations; + } + + /** + * Performs security checks on a given file path to ensure it is within + * the allowed project scope and doesn’t target restricted files. + * + * @param filePath - The path to be checked. + * @throws If the path is outside the project root or is otherwise disallowed. + */ private safetyChecks(filePath: string) { const targetPath = path.resolve(this.projectRoot, filePath); // Normalize path @@ -134,6 +238,13 @@ export class FileOperationManager { // } } + /** + * Checks if the targetPath is within one of the allowed paths + * and not in node_modules or environment files. + * + * @param targetPath - The path to check. + * @returns True if allowed, false otherwise. + */ private isPathAllowed(targetPath: string): boolean { return this.allowedPaths.some( (allowedPath) => diff --git a/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts b/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts deleted file mode 100644 index eced7371..00000000 --- a/backend/src/build-system/handlers/frontend-code-generate/FixResponseParser.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { FileOperation } from './FileOperationManager'; - -export class FixResponseParser { - private logger = console; - - // parse the gpt json input - parse(json: string, filePath: string): FileOperation[] { - this.logger.log('Parsing JSON:', json); - - let parsedData; - try { - parsedData = JSON.parse(json); - } catch (error) { - this.logger.error('Error parsing JSON:', error); - throw new Error('Invalid JSON format'); - } - - if (!parsedData.fix || !parsedData.fix.operation) { - throw new Error("Invalid JSON structure: Missing 'fix.operations'"); - } - - const op = parsedData.fix.operation; - const operations: FileOperation[] = []; - - if (op.type === 'WRITE') { - operations.push({ - action: 'write', - originalPath: filePath, - code: op.content?.trim(), - }); - } else if (op.type === 'RENAME') { - operations.push({ - action: 'rename', - originalPath: op.original_path, - renamePath: op.path, - }); - } else if (op.type === 'READ' && Array.isArray(op.paths)) { - for (const path of op.paths) { - operations.push({ - action: 'read', - originalPath: path, - }); - } - } - - // this.logger.log('Extracted operations:', operations); - return operations; - } -} diff --git a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts index a11b77e5..d283be00 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts @@ -1,6 +1,18 @@ +/** + * FrontendQueueProcessor.ts + * + * This file defines: + * 1) The `FileTask` interface, which describes the basic structure + * of tasks that the queue will handle. + * 2) The `CodeTaskQueue` class, a simple FIFO queue for tasks. + * 3) The `FrontendQueueProcessor` class, which orchestrates: + * - Writing files + * - Validating builds via `FrontendCodeValidator` + * - Attempting fixes (via LLM) if builds fail + */ + import { Logger } from '@nestjs/common'; -import { FrontendCodeValidator } from './FrontendCodeValidator'; -import { CodeTaskQueue, FileTask } from './CodeTaskQueue'; +import { FrontendCodeValidator } from './CodeValidator'; import { readFileSync } from 'fs'; import { chatSyncWithClocker } from 'src/build-system/utils/handler-helper'; import { createFileWithRetries } from 'src/build-system/utils/files'; @@ -11,11 +23,49 @@ import { generateFileOperationPrompt, } from './prompt'; import { FileOperationManager } from './FileOperationManager'; -import { FixResponseParser } from './FixResponseParser'; import normalizePath from 'normalize-path'; import path from 'path'; +/** + * Describes a single file task that the queue will process. + * + * @property filePath - The relative path to the file (e.g. "src/components/MyComp.ts"). + * @property fileContents - The code content for that file (usually generated by an LLM). + * @property dependenciesPath? - Optional: references to any internal dependency file(s). + */ +export interface FileTask { + filePath: string; // e.g. "src/components/MyComponent.ts" + fileContents: string; // the code you got from the LLM + dependenciesPath?: string; +} + +export class CodeTaskQueue { + private tasks: FileTask[] = []; + + enqueue(task: FileTask) { + this.tasks.push(task); + } + + dequeue(): FileTask | undefined { + return this.tasks.shift(); + } + + get size(): number { + return this.tasks.length; + } +} + +/** + * FrontendQueueProcessor + * + * This class orchestrates how each `FileTask` is handled: + * 1. Writes the file content to disk. + * 2. Runs a build/validation step (via `FrontendCodeValidator`). + * 3. If there is a build error, attempts to fix the file by + * invoking an LLM and performing the suggested operations. + * 4. Repeats until build succeeds or max attempts are reached. + */ export class FrontendQueueProcessor { private logger = new Logger('FrontendQueueProcessor'); @@ -122,7 +172,15 @@ export class FrontendQueueProcessor { } /** - * Fallback if you have no structured error details. + * Fallback fix method if no structured error details are available. + * This method interacts with an LLM to propose fixes and then + * executes those fixes via FileOperationManager. + * + * @param currentFullFilePath - The absolute path to the file being fixed. + * @param task - The original FileTask with code and path info. + * @param rawErrorText - The error text from the validator, fed to the LLM. + * + * @returns The new file path if the file was renamed, or null otherwise. */ private async fixFileGeneric( currentFullFilePath: string, @@ -142,7 +200,6 @@ export class FrontendQueueProcessor { this.frontendPath, this.renameMap, ); - const parser = new FixResponseParser(); //this.logger.log(fixPrompt); @@ -182,7 +239,7 @@ export class FrontendQueueProcessor { }, { role: 'assistant', - content: `Let me check my result and I must follow the output format`, + content: `Let me check my result and I must follow the output format.`, }, ], }, @@ -194,7 +251,10 @@ export class FrontendQueueProcessor { this.logger.debug('dependency file Paths ' + task.dependenciesPath); const parsed_fixResponse = removeCodeBlockFences(fixResponse); - let operations = parser.parse(parsed_fixResponse, task.filePath); + let operations = fileOperationManager.parse( + parsed_fixResponse, + task.filePath, + ); // **If LLM requested additional files, read them** if (operations.some((op) => op.action === 'read')) { @@ -270,7 +330,10 @@ export class FrontendQueueProcessor { 'Updated Fix Response with extra context: ' + fixResponse, ); const updated_fixResponse = removeCodeBlockFences(fixResponse); - operations = await parser.parse(updated_fixResponse, task.filePath); + operations = await fileOperationManager.parse( + updated_fixResponse, + task.filePath, + ); } const newFilePath = diff --git a/backend/src/build-system/handlers/frontend-code-generate/index.ts b/backend/src/build-system/handlers/frontend-code-generate/index.ts index e39b40a0..209abc3b 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/index.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/index.ts @@ -18,9 +18,11 @@ import { formatResponse } from 'src/build-system/utils/strings'; import { writeFileSync } from 'fs'; import { MessageInterface } from 'src/common/model-provider/types'; -import { CodeTaskQueue } from './CodeTaskQueue'; -import { FrontendCodeValidator } from './FrontendCodeValidator'; -import { FrontendQueueProcessor } from './FrontendQueueProcessor'; +import { FrontendCodeValidator } from './CodeValidator'; +import { + FrontendQueueProcessor, + CodeTaskQueue, +} from './FrontendQueueProcessor'; interface FileInfos { [fileName: string]: { From d3cbd0311444d898a20b460a83c1a58a5980b768 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Sun, 16 Feb 2025 22:43:48 -0500 Subject: [PATCH 18/18] update file name --- .../{FrontendQueueProcessor.ts => CodeReview.ts} | 0 .../build-system/handlers/frontend-code-generate/index.ts | 5 +---- 2 files changed, 1 insertion(+), 4 deletions(-) rename backend/src/build-system/handlers/frontend-code-generate/{FrontendQueueProcessor.ts => CodeReview.ts} (100%) diff --git a/backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts b/backend/src/build-system/handlers/frontend-code-generate/CodeReview.ts similarity index 100% rename from backend/src/build-system/handlers/frontend-code-generate/FrontendQueueProcessor.ts rename to backend/src/build-system/handlers/frontend-code-generate/CodeReview.ts diff --git a/backend/src/build-system/handlers/frontend-code-generate/index.ts b/backend/src/build-system/handlers/frontend-code-generate/index.ts index 209abc3b..3a6d46a3 100644 --- a/backend/src/build-system/handlers/frontend-code-generate/index.ts +++ b/backend/src/build-system/handlers/frontend-code-generate/index.ts @@ -19,10 +19,7 @@ import { writeFileSync } from 'fs'; import { MessageInterface } from 'src/common/model-provider/types'; import { FrontendCodeValidator } from './CodeValidator'; -import { - FrontendQueueProcessor, - CodeTaskQueue, -} from './FrontendQueueProcessor'; +import { FrontendQueueProcessor, CodeTaskQueue } from './CodeReview'; interface FileInfos { [fileName: string]: {