move write file to single and to bun based with separate prompt

This commit is contained in:
dal 2025-09-30 21:39:29 -06:00
parent cce3eaf009
commit b1aa4c4363
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
16 changed files with 547 additions and 978 deletions

View File

@ -63,5 +63,8 @@
"uuid": "^11.1.0",
"yaml": "^2.8.1",
"zod": "catalog:"
},
"devDependencies": {
"@types/bun": "^1.2.23"
}
}

View File

@ -6,6 +6,7 @@ import z from 'zod';
import { DEFAULT_ANTHROPIC_OPTIONS } from '../../llm/providers/gateway';
import { Sonnet4 } from '../../llm/sonnet-4';
import { bashExecute, createIdleTool } from '../../tools';
import { createWriteFileTool } from '../../tools/file-tools';
import { type AgentContext, repairToolCall } from '../../utils/tool-call-repair';
import { getDocsAgentSystemPrompt } from './get-docs-agent-system-prompt';
@ -52,6 +53,10 @@ export function createDocsAgent(docsAgentOptions: DocsAgentOptions) {
} as ModelMessage;
const idleTool = createIdleTool();
const writeFileTool = createWriteFileTool({
messageId: docsAgentOptions.messageId,
projectDirectory: docsAgentOptions.folder_structure,
});
// Create planning tools with simple context
async function stream({ messages }: DocsStreamOptions) {
@ -73,6 +78,7 @@ export function createDocsAgent(docsAgentOptions: DocsAgentOptions) {
providerOptions: DEFAULT_ANTHROPIC_OPTIONS,
tools: {
idleTool,
writeFileTool,
},
messages: [systemMessage, ...messages],
stopWhen: STOP_CONDITIONS,

View File

@ -0,0 +1,3 @@
# IMPORTANT
These tools are used in the CLI docs agent and use the Bun runtime to execute file operations.

View File

@ -1,54 +0,0 @@
import type { Sandbox } from '@buster/sandbox';
import { tool } from 'ai';
import { z } from 'zod';
import { createCreateFilesTool } from './create-files-tool';
// Re-export schemas and types for backward compatibility
const FileCreateParamsSchema = z.object({
path: z.string().describe('The relative or absolute path to create the file at'),
content: z.string().describe('The content to write to the file'),
});
export const CreateFilesInputSchema = z.object({
files: z.array(FileCreateParamsSchema).describe('Array of file creation operations to perform'),
});
const CreateFilesOutputSchema = z.object({
results: z.array(
z.discriminatedUnion('status', [
z.object({
status: z.literal('success'),
filePath: z.string(),
}),
z.object({
status: z.literal('error'),
filePath: z.string(),
errorMessage: z.string(),
}),
])
),
});
const CreateFilesContextSchema = z.object({
messageId: z.string().describe('The message ID for database updates'),
sandbox: z
.custom<Sandbox>(
(val) => {
return val && typeof val === 'object' && 'id' in val && 'fs' in val;
},
{ message: 'Invalid Sandbox instance' }
)
.describe('Sandbox instance for file operations'),
});
export type CreateFilesInput = z.infer<typeof CreateFilesInputSchema>;
export type CreateFilesOutput = z.infer<typeof CreateFilesOutputSchema>;
export type CreateFilesContext = z.infer<typeof CreateFilesContextSchema>;
// Factory function that creates the tool with context
export function createFiles(context: CreateFilesContext) {
return createCreateFilesTool(context);
}
// Default export using factory pattern - requires context to be passed
export default createFiles;

View File

@ -1,243 +0,0 @@
import { exec } from 'node:child_process';
import * as fs from 'node:fs/promises';
import * as os from 'node:os';
import * as path from 'node:path';
import { promisify } from 'node:util';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
const execAsync = promisify(exec);
// Helper to execute script with clean stderr
async function runScript(args: string) {
const { stdout, stderr } = await execAsync(
`npx tsx ${path.join(__dirname, 'create-files-script.ts')} ${args}`,
{ env: { ...process.env, npm_config_loglevel: 'error' } }
);
// Filter out npm warnings
const cleanStderr = stderr
.split('\n')
.filter((line) => !line.includes('npm warn') && line.trim() !== '')
.join('\n');
return { stdout, stderr: cleanStderr };
}
describe('create-files-script integration tests', () => {
let tempDir: string;
const scriptPath = path.join(__dirname, 'create-files-script.ts');
beforeEach(async () => {
// Create a temporary directory for test files
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'create-files-test-'));
});
afterEach(async () => {
// Clean up temporary directory
await fs.rm(tempDir, { recursive: true, force: true });
});
it('should create single file successfully', async () => {
const testFile = path.join(tempDir, 'test.txt');
const fileParams = [{ path: testFile, content: 'Hello, World!' }];
const { stdout, stderr } = await runScript(`'${JSON.stringify(fileParams)}'`);
expect(stderr).toBe('');
const results = JSON.parse(stdout);
expect(results).toHaveLength(1);
expect(results[0]).toEqual({
success: true,
filePath: testFile,
});
// Verify file was actually created
const content = await fs.readFile(testFile, 'utf-8');
expect(content).toBe('Hello, World!');
});
it('should create multiple files successfully', async () => {
const files = [
{ path: path.join(tempDir, 'file1.txt'), content: 'Content 1' },
{ path: path.join(tempDir, 'file2.txt'), content: 'Content 2' },
{ path: path.join(tempDir, 'subdir', 'file3.txt'), content: 'Content 3' },
];
const { stdout, stderr } = await runScript(`'${JSON.stringify(files)}'`);
expect(stderr).toBe('');
const results = JSON.parse(stdout);
expect(results).toHaveLength(3);
// Verify all files were created
for (let i = 0; i < files.length; i++) {
expect(results[i].success).toBe(true);
const content = await fs.readFile(files[i]!.path, 'utf-8');
expect(content).toBe(files[i]!.content);
}
// Verify subdirectory was created
const subdirStats = await fs.stat(path.join(tempDir, 'subdir'));
expect(subdirStats.isDirectory()).toBe(true);
});
it('should handle relative paths correctly', async () => {
const originalCwd = process.cwd();
process.chdir(tempDir);
try {
const fileParams = [
{ path: 'relative.txt', content: 'Relative content' },
{ path: './subdir/nested.txt', content: 'Nested content' },
];
const { stdout, stderr } = await runScript(`'${JSON.stringify(fileParams)}'`);
expect(stderr).toBe('');
const results = JSON.parse(stdout);
expect(results).toHaveLength(2);
expect(results[0].success).toBe(true);
expect(results[1].success).toBe(true);
// Verify files were created at correct locations
const relativeContent = await fs.readFile(path.join(tempDir, 'relative.txt'), 'utf-8');
expect(relativeContent).toBe('Relative content');
const nestedContent = await fs.readFile(path.join(tempDir, 'subdir', 'nested.txt'), 'utf-8');
expect(nestedContent).toBe('Nested content');
} finally {
process.chdir(originalCwd);
}
});
it('should overwrite existing files', async () => {
const testFile = path.join(tempDir, 'existing.txt');
await fs.writeFile(testFile, 'Original content');
const fileParams = [{ path: testFile, content: 'New content' }];
const { stdout, stderr } = await runScript(`'${JSON.stringify(fileParams)}'`);
expect(stderr).toBe('');
const results = JSON.parse(stdout);
expect(results[0].success).toBe(true);
// Verify file was overwritten
const content = await fs.readFile(testFile, 'utf-8');
expect(content).toBe('New content');
});
it('should handle special characters in content', async () => {
const testFile = path.join(tempDir, 'special.txt');
const specialContent = 'Line 1\nLine 2\tTabbed\r\nWindows line\n"Quoted"\nSingle';
const fileParams = [{ path: testFile, content: specialContent }];
const { stdout, stderr } = await runScript(`'${JSON.stringify(fileParams)}'`);
expect(stderr).toBe('');
const results = JSON.parse(stdout);
expect(results[0].success).toBe(true);
// Verify content with special characters
const content = await fs.readFile(testFile, 'utf-8');
expect(content).toBe(specialContent);
});
it('should handle errors gracefully', async () => {
// Try to create a file in a non-existent absolute path
const invalidPath = '/this/path/should/not/exist/file.txt';
const fileParams = [{ path: invalidPath, content: 'Content' }];
const { stdout, stderr } = await runScript(`'${JSON.stringify(fileParams)}'`);
expect(stderr).toBe('');
const results = JSON.parse(stdout);
expect(results[0].success).toBe(false);
expect(results[0].filePath).toBe(invalidPath);
expect(results[0].error).toBeTruthy();
});
it('should handle mixed success and failure', async () => {
const files = [
{ path: path.join(tempDir, 'success1.txt'), content: 'Success 1' },
{ path: '/invalid/path/fail.txt', content: 'Will fail' },
{ path: path.join(tempDir, 'success2.txt'), content: 'Success 2' },
];
const { stdout, stderr } = await runScript(`'${JSON.stringify(files)}'`);
expect(stderr).toBe('');
const results = JSON.parse(stdout);
expect(results).toHaveLength(3);
expect(results[0].success).toBe(true);
expect(results[1].success).toBe(false);
expect(results[2].success).toBe(true);
// Verify successful files were created
const content1 = await fs.readFile(files[0]!.path, 'utf-8');
expect(content1).toBe('Success 1');
const content2 = await fs.readFile(files[2]!.path, 'utf-8');
expect(content2).toBe('Success 2');
});
it('should error when no arguments provided', async () => {
try {
const { stdout, stderr } = await execAsync(`npx tsx ${scriptPath}`, {
env: { ...process.env, npm_config_loglevel: 'error' },
});
expect.fail('Should have thrown an error');
} catch (error: any) {
expect(error.code).toBe(1);
const errorOutput = JSON.parse(error.stdout || error.stderr);
expect(errorOutput[0].success).toBe(false);
expect(errorOutput[0].error).toBe('No arguments provided to script');
}
});
it('should error with invalid JSON', async () => {
try {
const { stdout, stderr } = await execAsync(`npx tsx ${scriptPath} 'not valid json'`, {
env: { ...process.env, npm_config_loglevel: 'error' },
});
expect.fail('Should have thrown an error');
} catch (error: any) {
expect(error.code).toBe(1);
const errorOutput = JSON.parse(error.stdout || error.stderr);
expect(errorOutput[0].success).toBe(false);
expect(errorOutput[0].error).toContain('Failed to parse arguments');
}
});
it('should error with invalid parameter structure', async () => {
try {
const invalidParams = [{ path: '/test/file.txt' }]; // missing content
const { stdout, stderr } = await execAsync(
`npx tsx ${scriptPath} '${JSON.stringify(invalidParams)}'`,
{ env: { ...process.env, npm_config_loglevel: 'error' } }
);
expect.fail('Should have thrown an error');
} catch (error: any) {
expect(error.code).toBe(1);
const errorOutput = JSON.parse(error.stdout || error.stderr);
expect(errorOutput[0].success).toBe(false);
expect(errorOutput[0].error).toContain('must have a content string');
}
});
it('should create deeply nested directories', async () => {
const deepPath = path.join(tempDir, 'a', 'b', 'c', 'd', 'e', 'file.txt');
const fileParams = [{ path: deepPath, content: 'Deep content' }];
const { stdout, stderr } = await runScript(`'${JSON.stringify(fileParams)}'`);
expect(stderr).toBe('');
const results = JSON.parse(stdout);
expect(results[0].success).toBe(true);
// Verify file and all directories were created
const content = await fs.readFile(deepPath, 'utf-8');
expect(content).toBe('Deep content');
});
});

View File

@ -1,334 +0,0 @@
import * as child_process from 'node:child_process';
import * as fs from 'node:fs/promises';
import * as os from 'node:os';
import * as path from 'node:path';
import { promisify } from 'node:util';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
const exec = promisify(child_process.exec);
describe('create-files-script', () => {
const scriptPath = path.join(__dirname, 'create-files-script.ts');
let tempDir: string;
beforeEach(async () => {
// Create a temporary directory for test files
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'create-files-test-'));
});
afterEach(async () => {
// Clean up temporary directory
try {
await fs.rm(tempDir, { recursive: true, force: true });
} catch (error) {
// Ignore cleanup errors
}
});
async function runScript(args: string[]): Promise<{ stdout: string; stderr: string }> {
// Properly escape arguments for shell
const escapedArgs = args.map((arg) => {
// If it contains special characters, wrap in single quotes
if (arg.includes(' ') || arg.includes('"') || arg.includes('[') || arg.includes(']')) {
return `'${arg.replace(/'/g, "'\"'\"'")}'`;
}
return arg;
});
const { stdout, stderr } = await exec(`npx tsx ${scriptPath} ${escapedArgs.join(' ')}`);
return { stdout, stderr };
}
describe('functional tests', () => {
it('should create a single file successfully', async () => {
const testFile = path.join(tempDir, 'test.txt');
const fileParams = [
{
path: testFile,
content: 'Hello, world!',
},
];
const { stdout } = await runScript([JSON.stringify(fileParams)]);
const results = JSON.parse(stdout);
expect(results).toEqual([
{
success: true,
filePath: testFile,
},
]);
// Verify file was created
const content = await fs.readFile(testFile, 'utf-8');
expect(content).toBe('Hello, world!');
});
it('should create multiple files', async () => {
const fileParams = [
{ path: path.join(tempDir, 'file1.txt'), content: 'Content 1' },
{ path: path.join(tempDir, 'file2.txt'), content: 'Content 2' },
{ path: path.join(tempDir, 'file3.txt'), content: 'Content 3' },
];
const { stdout } = await runScript([JSON.stringify(fileParams)]);
const results = JSON.parse(stdout);
expect(results).toHaveLength(3);
expect(results.every((r: any) => r.success)).toBe(true);
// Verify all files were created
for (const param of fileParams) {
const content = await fs.readFile(param.path, 'utf-8');
expect(content).toBe(param.content);
}
});
it('should create directories if they do not exist', async () => {
const nestedFile = path.join(tempDir, 'nested', 'deep', 'file.txt');
const fileParams = [
{
path: nestedFile,
content: 'Nested content',
},
];
const { stdout } = await runScript([JSON.stringify(fileParams)]);
const results = JSON.parse(stdout);
expect(results[0].success).toBe(true);
// Verify file and directories were created
const content = await fs.readFile(nestedFile, 'utf-8');
expect(content).toBe('Nested content');
});
it('should handle relative paths', async () => {
const originalCwd = process.cwd();
try {
// Change to temp directory
process.chdir(tempDir);
const fileParams = [
{ path: 'relative.txt', content: 'Relative content' },
{ path: './subdir/file.txt', content: 'Subdir content' },
];
const { stdout } = await runScript([JSON.stringify(fileParams)]);
const results = JSON.parse(stdout);
expect(results).toHaveLength(2);
expect(results[0].success).toBe(true);
expect(results[1].success).toBe(true);
// Verify files were created
expect(await fs.readFile('relative.txt', 'utf-8')).toBe('Relative content');
expect(await fs.readFile('./subdir/file.txt', 'utf-8')).toBe('Subdir content');
} finally {
process.chdir(originalCwd);
}
});
it('should handle base64 encoded input', async () => {
const testFile = path.join(tempDir, 'base64.txt');
const fileParams = [{ path: testFile, content: 'Base64 content' }];
const base64Input = Buffer.from(JSON.stringify(fileParams)).toString('base64');
const { stdout } = await runScript([base64Input]);
const results = JSON.parse(stdout);
expect(results[0].success).toBe(true);
const content = await fs.readFile(testFile, 'utf-8');
expect(content).toBe('Base64 content');
});
it('should handle empty content', async () => {
const testFile = path.join(tempDir, 'empty.txt');
const fileParams = [{ path: testFile, content: '' }];
const { stdout } = await runScript([JSON.stringify(fileParams)]);
const results = JSON.parse(stdout);
expect(results[0].success).toBe(true);
const content = await fs.readFile(testFile, 'utf-8');
expect(content).toBe('');
});
it('should handle special characters in content', async () => {
const testFile = path.join(tempDir, 'special.txt');
const specialContent =
'Special chars: @#$%^&*()\n"Quotes"\n\'Apostrophes\'\n\tTabs\n\\Backslashes\\';
const fileParams = [{ path: testFile, content: specialContent }];
const { stdout } = await runScript([JSON.stringify(fileParams)]);
const results = JSON.parse(stdout);
expect(results[0].success).toBe(true);
const content = await fs.readFile(testFile, 'utf-8');
expect(content).toBe(specialContent);
});
it('should handle multiline content', async () => {
const testFile = path.join(tempDir, 'multiline.txt');
const multilineContent = `Line 1
Line 2
Line 3
Line 5 (after empty line)`;
const fileParams = [{ path: testFile, content: multilineContent }];
const { stdout } = await runScript([JSON.stringify(fileParams)]);
const results = JSON.parse(stdout);
expect(results[0].success).toBe(true);
const content = await fs.readFile(testFile, 'utf-8');
expect(content).toBe(multilineContent);
});
it('should handle files with spaces in names', async () => {
const testFile = path.join(tempDir, 'file with spaces.txt');
const fileParams = [{ path: testFile, content: 'Content with spaces' }];
const { stdout } = await runScript([JSON.stringify(fileParams)]);
const results = JSON.parse(stdout);
expect(results[0].success).toBe(true);
const content = await fs.readFile(testFile, 'utf-8');
expect(content).toBe('Content with spaces');
});
it('should handle no arguments', async () => {
try {
await runScript([]);
// Should not reach here
expect(true).toBe(false);
} catch (error: any) {
// Script exits with code 1
const results = JSON.parse(error.stdout);
expect(results).toEqual([
{
success: false,
filePath: '',
error: 'No arguments provided to script',
},
]);
}
});
it('should handle invalid JSON', async () => {
try {
await runScript(['not valid json']);
// Should not reach here
expect(true).toBe(false);
} catch (error: any) {
// Script exits with code 1
const results = JSON.parse(error.stdout);
expect(results[0].success).toBe(false);
expect(results[0].error).toContain('Failed to parse arguments');
}
});
it('should handle non-array input', async () => {
try {
await runScript(['{"not": "array"}']);
// Should not reach here
expect(true).toBe(false);
} catch (error: any) {
// Script exits with code 1
const results = JSON.parse(error.stdout);
expect(results[0].success).toBe(false);
expect(results[0].error).toContain('File parameters must be an array');
}
});
it('should handle missing path', async () => {
const fileParams = [{ content: 'No path provided' }];
try {
await runScript([JSON.stringify(fileParams)]);
// Should not reach here
expect(true).toBe(false);
} catch (error: any) {
// Script exits with code 1
const results = JSON.parse(error.stdout);
expect(results[0].success).toBe(false);
expect(results[0].error).toContain('must have a valid path string');
}
});
it('should handle missing content', async () => {
const fileParams = [{ path: 'test.txt' }];
try {
await runScript([JSON.stringify(fileParams)]);
// Should not reach here
expect(true).toBe(false);
} catch (error: any) {
// Script exits with code 1
const results = JSON.parse(error.stdout);
expect(results[0].success).toBe(false);
expect(results[0].error).toContain('must have a content string');
}
});
it('should handle mixed success and failure', async () => {
const file1 = path.join(tempDir, 'success.txt');
const file2 = path.join(tempDir, 'readonly', 'fail.txt');
// Create a readonly directory
const readonlyDir = path.join(tempDir, 'readonly');
await fs.mkdir(readonlyDir);
await fs.chmod(readonlyDir, 0o444);
const fileParams = [
{ path: file1, content: 'Success' },
{ path: file2, content: 'This will fail' },
];
const { stdout } = await runScript([JSON.stringify(fileParams)]);
const results = JSON.parse(stdout);
expect(results).toHaveLength(2);
expect(results[0].success).toBe(true);
expect(results[1].success).toBe(false);
// Verify successful file was created
const content = await fs.readFile(file1, 'utf-8');
expect(content).toBe('Success');
// Clean up
await fs.chmod(readonlyDir, 0o755);
});
it('should avoid creating duplicate directories', async () => {
// Multiple files in the same directory
const fileParams = [
{ path: path.join(tempDir, 'same-dir', 'file1.txt'), content: 'File 1' },
{ path: path.join(tempDir, 'same-dir', 'file2.txt'), content: 'File 2' },
{ path: path.join(tempDir, 'same-dir', 'file3.txt'), content: 'File 3' },
];
const { stdout } = await runScript([JSON.stringify(fileParams)]);
const results = JSON.parse(stdout);
expect(results).toHaveLength(3);
expect(results.every((r: any) => r.success)).toBe(true);
// Verify all files were created
for (const param of fileParams) {
const content = await fs.readFile(param.path, 'utf-8');
expect(content).toBe(param.content);
}
});
it('should handle UTF-8 content', async () => {
const testFile = path.join(tempDir, 'utf8.txt');
const utf8Content = '你好世界 🌍 Émojis and special chars: €£¥';
const fileParams = [{ path: testFile, content: utf8Content }];
const { stdout } = await runScript([JSON.stringify(fileParams)]);
const results = JSON.parse(stdout);
expect(results[0].success).toBe(true);
const content = await fs.readFile(testFile, 'utf-8');
expect(content).toBe(utf8Content);
});
});
});

View File

@ -1,147 +0,0 @@
import * as fs from 'node:fs/promises';
import * as path from 'node:path';
interface FileCreateParams {
path: string;
content: string;
}
interface FileCreateResult {
success: boolean;
filePath: string;
error?: string;
}
async function createFiles(fileParams: FileCreateParams[]): Promise<FileCreateResult[]> {
const results: FileCreateResult[] = [];
const createdDirs = new Set<string>();
// Process files sequentially to avoid race conditions
for (const { path: filePath, content } of fileParams) {
try {
const resolvedPath = path.isAbsolute(filePath)
? filePath
: path.join(process.cwd(), filePath);
const dirPath = path.dirname(resolvedPath);
// Only create directory if we haven't already created it
if (!createdDirs.has(dirPath)) {
try {
await fs.mkdir(dirPath, { recursive: true });
createdDirs.add(dirPath);
} catch (error) {
results.push({
success: false,
filePath,
error: `Failed to create directory: ${error instanceof Error ? error.message : 'Unknown error'}`,
});
continue;
}
}
await fs.writeFile(resolvedPath, content, 'utf-8');
results.push({
success: true,
filePath,
});
} catch (error) {
results.push({
success: false,
filePath,
error: error instanceof Error ? error.message : 'Unknown error occurred',
});
}
}
return results;
}
// Script execution
async function main() {
// Parse command line arguments
const args = process.argv.slice(2);
if (args.length === 0) {
console.log(
JSON.stringify([
{
success: false,
filePath: '',
error: 'No arguments provided to script',
},
])
);
process.exit(1);
}
let fileParams: FileCreateParams[];
try {
// The script expects file parameters as a JSON string in the first argument (possibly base64 encoded)
let fileParamsJson = args[0];
if (!fileParamsJson) {
throw new Error('No argument provided');
}
// Try to decode from base64 if it looks like base64
if (
fileParamsJson &&
/^[A-Za-z0-9+/]+=*$/.test(fileParamsJson) &&
fileParamsJson.length % 4 === 0
) {
try {
fileParamsJson = Buffer.from(fileParamsJson, 'base64').toString('utf-8');
} catch {
// If base64 decode fails, use as-is
}
}
fileParams = JSON.parse(fileParamsJson);
if (!Array.isArray(fileParams)) {
throw new Error('File parameters must be an array');
}
// Validate each file parameter
for (const param of fileParams) {
if (!param.path || typeof param.path !== 'string') {
throw new Error('Each file parameter must have a valid path string');
}
if (typeof param.content !== 'string') {
throw new Error('Each file parameter must have a content string');
}
}
} catch (error) {
// Return error information instead of empty array
console.log(
JSON.stringify([
{
success: false,
filePath: '',
error: `Failed to parse arguments: ${error instanceof Error ? error.message : 'Unknown error'}`,
},
])
);
process.exit(1);
}
const results = await createFiles(fileParams);
// Output as JSON to stdout
console.log(JSON.stringify(results));
}
// Run the script
main().catch((error) => {
// Return error information for unexpected errors
console.log(
JSON.stringify([
{
success: false,
filePath: '',
error: `Unexpected error: ${error instanceof Error ? error.message : 'Unknown error'}`,
},
])
);
process.exit(1);
});

View File

@ -1,148 +0,0 @@
import { runTypescript } from '@buster/sandbox';
import { wrapTraced } from 'braintrust';
import type {
CreateFilesToolContext,
CreateFilesToolInput,
CreateFilesToolOutput,
} from './create-files-tool';
export function createCreateFilesToolExecute(context: CreateFilesToolContext) {
return wrapTraced(
async (input: CreateFilesToolInput): Promise<CreateFilesToolOutput> => {
const { files } = input;
if (!files || files.length === 0) {
return { results: [] };
}
try {
const sandbox = context.sandbox;
if (!sandbox) {
return {
results: files.map((file) => ({
status: 'error' as const,
filePath: file.path,
errorMessage: 'File creation requires sandbox environment',
})),
};
}
// Generate CommonJS code for sandbox execution
const filesJson = JSON.stringify(files);
const sandboxCode = `
const fs = require('fs');
const path = require('path');
const filesJson = ${JSON.stringify(filesJson)};
const files = JSON.parse(filesJson);
const results = [];
const createdDirs = new Set();
// Process files sequentially
for (const file of files) {
try {
const resolvedPath = path.isAbsolute(file.path)
? file.path
: path.join(process.cwd(), file.path);
const dirPath = path.dirname(resolvedPath);
// Only create directory if we haven't already created it
if (!createdDirs.has(dirPath)) {
try {
fs.mkdirSync(dirPath, { recursive: true });
createdDirs.add(dirPath);
} catch (error) {
results.push({
success: false,
filePath: file.path,
error: 'Failed to create directory: ' + (error instanceof Error ? error.message : String(error))
});
continue;
}
}
fs.writeFileSync(resolvedPath, file.content, 'utf-8');
results.push({
success: true,
filePath: file.path
});
} catch (error) {
results.push({
success: false,
filePath: file.path,
error: (error instanceof Error ? error.message : String(error)) || 'Unknown error'
});
}
}
console.log(JSON.stringify(results));
`;
const result = await runTypescript(sandbox, sandboxCode);
if (result.exitCode !== 0) {
console.error('Sandbox execution failed. Exit code:', result.exitCode);
console.error('Stderr:', result.stderr);
console.error('Result:', result.result);
throw new Error(`Sandbox execution failed: ${result.stderr || 'Unknown error'}`);
}
// Debug logging to see what we're getting
console.info('Raw sandbox result:', result.result);
console.info('Trimmed result:', result.result.trim());
console.info('Result type:', typeof result.result);
let fileResults: Array<{
success: boolean;
filePath: string;
error?: string;
}>;
try {
fileResults = JSON.parse(result.result.trim());
// Additional validation
if (!Array.isArray(fileResults)) {
console.error('Parsed result is not an array:', fileResults);
throw new Error('Parsed result is not an array');
}
} catch (parseError) {
console.error('Failed to parse sandbox output:', result.result);
throw new Error(
`Failed to parse sandbox output: ${parseError instanceof Error ? parseError.message : 'Unknown parse error'}`
);
}
const output: CreateFilesToolOutput = {
results: fileResults.map((fileResult) => {
if (fileResult.success) {
return {
status: 'success' as const,
filePath: fileResult.filePath,
};
}
return {
status: 'error' as const,
filePath: fileResult.filePath,
errorMessage: fileResult.error || 'Unknown error',
};
}),
};
return output;
} catch (error) {
const errorOutput: CreateFilesToolOutput = {
results: files.map((file) => ({
status: 'error' as const,
filePath: file.path,
errorMessage: `Execution error: ${error instanceof Error ? error.message : 'Unknown error'}`,
})),
};
return errorOutput;
}
},
{ name: 'create-files' }
);
}

View File

@ -1,7 +1,7 @@
export { createBashTool, bashExecute } from './bash-tool';
export { createListFilesTool } from './list-files-tool/list-files-tool';
export { createReadFilesTool } from './read-files-tool/read-files-tool';
export { createCreateFilesTool } from './create-files-tool/create-files-tool';
export { createWriteFileTool } from './write-file-tool/write-file-tool';
export { createEditFilesTool } from './edit-files-tool/edit-files-tool';
export { createDeleteFilesTool } from './delete-files-tool/delete-files-tool';
export { createGrepSearchTool } from './grep-search-tool/grep-search-tool';

View File

@ -0,0 +1,328 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import type { WriteFileToolInput } from './write-file-tool';
import { createWriteFileToolExecute } from './write-file-tool-execute';
// Mock Bun global
const mockBunFile = vi.fn();
const mockBunWrite = vi.fn();
global.Bun = {
file: mockBunFile,
write: mockBunWrite,
} as unknown as typeof Bun;
describe('createWriteFileToolExecute', () => {
const projectDirectory = '/project';
const messageId = 'test-message-id';
beforeEach(() => {
vi.clearAllMocks();
vi.spyOn(console, 'info').mockImplementation(() => { });
vi.spyOn(console, 'error').mockImplementation(() => { });
});
afterEach(() => {
vi.restoreAllMocks();
});
describe('successful file creation', () => {
it('should create a single new file successfully', async () => {
// Setup
const mockFile = {
exists: vi.fn().mockResolvedValue(false),
};
mockBunFile.mockReturnValue(mockFile);
mockBunWrite.mockResolvedValue(undefined);
const execute = createWriteFileToolExecute({ messageId, projectDirectory });
const input: WriteFileToolInput = {
files: [
{
path: 'test.ts',
content: 'export const test = "hello";',
},
],
};
// Execute
const result = await execute(input);
// Verify
expect(result.results).toHaveLength(1);
expect(result.results[0]).toEqual({
status: 'success',
filePath: '/project/test.ts',
});
expect(mockBunFile).toHaveBeenCalledWith('/project/test.ts');
expect(mockFile.exists).toHaveBeenCalled();
expect(mockBunWrite).toHaveBeenCalledWith('/project/test.ts', 'export const test = "hello";');
});
it('should overwrite an existing file successfully', async () => {
// Setup
const mockFile = {
exists: vi.fn().mockResolvedValue(true),
};
mockBunFile.mockReturnValue(mockFile);
mockBunWrite.mockResolvedValue(undefined);
const execute = createWriteFileToolExecute({ messageId, projectDirectory });
const input: WriteFileToolInput = {
files: [
{
path: 'existing.ts',
content: 'updated content',
},
],
};
// Execute
const result = await execute(input);
// Verify
expect(result.results).toHaveLength(1);
expect(result.results[0]).toEqual({
status: 'success',
filePath: '/project/existing.ts',
});
expect(mockBunWrite).toHaveBeenCalledWith('/project/existing.ts', 'updated content');
});
it('should create multiple files in parallel', async () => {
// Setup
const mockFile = {
exists: vi.fn().mockResolvedValue(false),
};
mockBunFile.mockReturnValue(mockFile);
mockBunWrite.mockResolvedValue(undefined);
const execute = createWriteFileToolExecute({ messageId, projectDirectory });
const input: WriteFileToolInput = {
files: [
{ path: 'file1.ts', content: 'content1' },
{ path: 'file2.ts', content: 'content2' },
{ path: 'file3.ts', content: 'content3' },
],
};
// Execute
const result = await execute(input);
// Verify
expect(result.results).toHaveLength(3);
expect(result.results.every((r) => r.status === 'success')).toBe(true);
expect(mockBunWrite).toHaveBeenCalledTimes(3);
});
it('should handle absolute paths correctly', async () => {
// Setup
const mockFile = {
exists: vi.fn().mockResolvedValue(false),
};
mockBunFile.mockReturnValue(mockFile);
mockBunWrite.mockResolvedValue(undefined);
const execute = createWriteFileToolExecute({ messageId, projectDirectory });
const input: WriteFileToolInput = {
files: [
{
path: '/project/absolute/path.ts',
content: 'absolute content',
},
],
};
// Execute
const result = await execute(input);
// Verify
expect(result.results).toHaveLength(1);
expect(result.results[0]).toEqual({
status: 'success',
filePath: '/project/absolute/path.ts',
});
});
});
describe('error handling', () => {
it('should handle file write errors gracefully', async () => {
// Setup
const mockFile = {
exists: vi.fn().mockResolvedValue(false),
};
mockBunFile.mockReturnValue(mockFile);
mockBunWrite.mockRejectedValue(new Error('Permission denied'));
const execute = createWriteFileToolExecute({ messageId, projectDirectory });
const input: WriteFileToolInput = {
files: [
{
path: 'error.ts',
content: 'content',
},
],
};
// Execute
const result = await execute(input);
// Verify
expect(result.results).toHaveLength(1);
expect(result.results[0]).toEqual({
status: 'error',
filePath: 'error.ts',
errorMessage: 'Permission denied',
});
});
it('should reject paths outside project directory', async () => {
// Setup
const execute = createWriteFileToolExecute({ messageId, projectDirectory });
const input: WriteFileToolInput = {
files: [
{
path: '../outside/project.ts',
content: 'malicious content',
},
],
};
// Execute
const result = await execute(input);
// Verify
expect(result.results).toHaveLength(1);
const firstResult = result.results[0];
if (!firstResult) {
throw new Error('Expected first result to exist');
}
expect(firstResult.status).toBe('error');
if (firstResult.status === 'error') {
expect(firstResult.errorMessage).toContain('not in the current working directory');
}
});
it('should handle mixed success and failure', async () => {
// Setup
const mockFile = {
exists: vi.fn().mockResolvedValue(false),
};
mockBunFile.mockReturnValue(mockFile);
mockBunWrite
.mockResolvedValueOnce(undefined) // First succeeds
.mockRejectedValueOnce(new Error('Write failed')) // Second fails
.mockResolvedValueOnce(undefined); // Third succeeds
const execute = createWriteFileToolExecute({ messageId, projectDirectory });
const input: WriteFileToolInput = {
files: [
{ path: 'success1.ts', content: 'content1' },
{ path: 'failure.ts', content: 'content2' },
{ path: 'success2.ts', content: 'content3' },
],
};
// Execute
const result = await execute(input);
// Verify
expect(result.results).toHaveLength(3);
if (!result.results[0] || !result.results[1] || !result.results[2]) {
throw new Error('Expected all results to exist');
}
expect(result.results[0].status).toBe('success');
expect(result.results[1].status).toBe('error');
expect(result.results[2].status).toBe('success');
});
it('should reject absolute paths outside project directory', async () => {
// Setup
const execute = createWriteFileToolExecute({ messageId, projectDirectory });
const input: WriteFileToolInput = {
files: [
{
path: '/etc/passwd',
content: 'malicious',
},
],
};
// Execute
const result = await execute(input);
// Verify
expect(result.results).toHaveLength(1);
const firstResult = result.results[0];
if (!firstResult) {
throw new Error('Expected first result to exist');
}
expect(firstResult.status).toBe('error');
if (firstResult.status === 'error') {
expect(firstResult.errorMessage).toContain('not in the current working directory');
}
});
});
describe('path handling', () => {
it('should handle nested directory paths', async () => {
// Setup
const mockFile = {
exists: vi.fn().mockResolvedValue(false),
};
mockBunFile.mockReturnValue(mockFile);
mockBunWrite.mockResolvedValue(undefined);
const execute = createWriteFileToolExecute({ messageId, projectDirectory });
const input: WriteFileToolInput = {
files: [
{
path: 'src/components/Button.tsx',
content: 'export const Button = () => {};',
},
],
};
// Execute
const result = await execute(input);
// Verify
expect(result.results).toHaveLength(1);
expect(result.results[0]).toEqual({
status: 'success',
filePath: '/project/src/components/Button.tsx',
});
});
it('should normalize paths correctly', async () => {
// Setup
const mockFile = {
exists: vi.fn().mockResolvedValue(false),
};
mockBunFile.mockReturnValue(mockFile);
mockBunWrite.mockResolvedValue(undefined);
const execute = createWriteFileToolExecute({ messageId, projectDirectory });
const input: WriteFileToolInput = {
files: [
{
path: './src/../lib/utils.ts',
content: 'utils',
},
],
};
// Execute
const result = await execute(input);
// Verify
const firstResult = result.results[0];
if (!firstResult) {
throw new Error('Expected first result to exist');
}
expect(firstResult.status).toBe('success');
expect(firstResult.filePath).toBe('/project/lib/utils.ts');
});
});
});

View File

@ -0,0 +1,132 @@
import path from 'node:path';
import type {
WriteFileToolContext,
WriteFileToolInput,
WriteFileToolOutput,
} from './write-file-tool';
/**
* Validates that a file path is safe and within the project directory
* @param filePath - The file path to validate
* @param projectDirectory - The root directory of the project
* @throws Error if the path is unsafe or outside the project
*/
function validateFilePath(filePath: string, projectDirectory: string): void {
// Convert to absolute path if relative
const absolutePath = path.isAbsolute(filePath) ? filePath : path.join(projectDirectory, filePath);
// Normalize to resolve any '..' or '.' components
const normalizedPath = path.normalize(absolutePath);
const normalizedProject = path.normalize(projectDirectory);
// Ensure the resolved path is within the project directory
if (!normalizedPath.startsWith(normalizedProject)) {
throw new Error(`File ${filePath} is not in the current working directory ${projectDirectory}`);
}
}
/**
* Creates a single file using Bun's filesystem API
* @param filePath - The file path to create (absolute or relative)
* @param content - The content to write
* @param projectDirectory - The root directory of the project
* @returns Result object with success status and details
*/
async function createSingleFile(
filePath: string,
content: string,
projectDirectory: string
): Promise<{
status: 'success' | 'error';
filePath: string;
errorMessage?: string;
existed?: boolean;
}> {
try {
// Convert to absolute path if relative
const absolutePath = path.isAbsolute(filePath)
? filePath
: path.join(projectDirectory, filePath);
// Validate the file path is within the project directory
validateFilePath(absolutePath, projectDirectory);
// Check if file already exists
const file = Bun.file(absolutePath);
const existed = await file.exists();
if (existed) {
console.info(`Overwriting existing file: ${absolutePath}`);
} else {
console.info(`Creating new file: ${absolutePath}`);
}
// Write the file content (Bun automatically creates parent directories)
await Bun.write(absolutePath, content);
console.info(`Successfully ${existed ? 'updated' : 'created'} file: ${absolutePath}`);
return {
status: 'success',
filePath: absolutePath,
existed,
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
console.error(`Error creating file ${filePath}:`, errorMessage);
return {
status: 'error',
filePath,
errorMessage,
};
}
}
/**
* Creates the execute function for the create files tool
* @param context - The tool context containing messageId and project directory
* @returns The execute function
*/
export function createWriteFileToolExecute(context: WriteFileToolContext) {
return async function execute(input: WriteFileToolInput): Promise<WriteFileToolOutput> {
const { messageId, projectDirectory } = context;
const { files } = input;
console.info(`Creating ${files.length} file(s) for message ${messageId}`);
// Process all files in parallel
const fileResults = await Promise.all(
files.map((file) => createSingleFile(file.path, file.content, projectDirectory))
);
// Format results according to the output schema
const results = fileResults.map((result) => {
if (result.status === 'success') {
return {
status: 'success' as const,
filePath: result.filePath,
};
}
return {
status: 'error' as const,
filePath: result.filePath,
errorMessage: result.errorMessage || 'Unknown error occurred',
};
});
// Log summary
const successCount = results.filter((r) => r.status === 'success').length;
const errorCount = results.filter((r) => r.status === 'error').length;
console.info(`File creation complete: ${successCount} succeeded, ${errorCount} failed`);
if (errorCount > 0) {
const errors = results.filter((r) => r.status === 'error');
console.error('Failed files:', errors);
}
return { results };
};
}

View File

@ -1,18 +1,17 @@
import type { Sandbox } from '@buster/sandbox';
import { tool } from 'ai';
import { z } from 'zod';
import { createCreateFilesToolExecute } from './create-files-tool-execute';
import { createWriteFileToolExecute } from './write-file-tool-execute';
const FileCreateParamsSchema = z.object({
path: z.string().describe('The relative or absolute path to create the file at'),
content: z.string().describe('The content to write to the file'),
});
export const CreateFilesToolInputSchema = z.object({
export const WriteFileToolInputSchema = z.object({
files: z.array(FileCreateParamsSchema).describe('Array of file creation operations to perform'),
});
const CreateFilesToolOutputSchema = z.object({
const WriteFileToolOutputSchema = z.object({
results: z.array(
z.discriminatedUnion('status', [
z.object({
@ -28,31 +27,24 @@ const CreateFilesToolOutputSchema = z.object({
),
});
const CreateFilesToolContextSchema = z.object({
const WriteFileToolContextSchema = z.object({
messageId: z.string().describe('The message ID for database updates'),
sandbox: z
.custom<Sandbox>(
(val) => {
return val && typeof val === 'object' && 'id' in val && 'fs' in val;
},
{ message: 'Invalid Sandbox instance' }
)
.describe('Sandbox instance for file operations'),
projectDirectory: z.string().describe('The root directory of the project'),
});
export type CreateFilesToolInput = z.infer<typeof CreateFilesToolInputSchema>;
export type CreateFilesToolOutput = z.infer<typeof CreateFilesToolOutputSchema>;
export type CreateFilesToolContext = z.infer<typeof CreateFilesToolContextSchema>;
export type WriteFileToolInput = z.infer<typeof WriteFileToolInputSchema>;
export type WriteFileToolOutput = z.infer<typeof WriteFileToolOutputSchema>;
export type WriteFileToolContext = z.infer<typeof WriteFileToolContextSchema>;
export function createCreateFilesTool<
TAgentContext extends CreateFilesToolContext = CreateFilesToolContext,
export function createWriteFileTool<
TAgentContext extends WriteFileToolContext = WriteFileToolContext,
>(context: TAgentContext) {
const execute = createCreateFilesToolExecute(context);
const execute = createWriteFileToolExecute(context);
return tool({
description: `Create one or more files at specified paths with provided content. Supports both absolute and relative file paths. Creates directories if they don't exist and overwrites existing files. Handles errors gracefully by continuing to process other files even if some fail. Returns both successful operations and failed operations with detailed error messages.`,
inputSchema: CreateFilesToolInputSchema,
outputSchema: CreateFilesToolOutputSchema,
inputSchema: WriteFileToolInputSchema,
outputSchema: WriteFileToolOutputSchema,
execute,
});
}

View File

@ -0,0 +1,8 @@
Writes a file to the local filesystem.
Usage:
- This tool will overwrite the existing file if there is one at the provided path.
- If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.
- ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.
- NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.
- Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked.

View File

@ -14,7 +14,7 @@ export { executeSqlDocsAgent } from './database-tools/super-execute-sql/super-ex
// File tools - factory functions
export { createListFilesTool } from './file-tools/list-files-tool/list-files-tool';
export { createReadFilesTool } from './file-tools/read-files-tool/read-files-tool';
export { createCreateFilesTool } from './file-tools/create-files-tool/create-files-tool';
export { createWriteFileTool } from './file-tools/write-file-tool/write-file-tool';
export { createEditFilesTool } from './file-tools/edit-files-tool/edit-files-tool';
export { createDeleteFilesTool } from './file-tools/delete-files-tool/delete-files-tool';
export { createBashTool } from './file-tools/bash-tool';

View File

@ -296,7 +296,7 @@ importers:
version: 5.0.44(zod@3.25.76)
drizzle-orm:
specifier: 'catalog:'
version: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
version: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
hono:
specifier: 'catalog:'
version: 4.9.7
@ -398,7 +398,7 @@ importers:
version: 0.3.7(@aws-sdk/credential-provider-web-identity@3.888.0)(zod@3.25.76)
drizzle-orm:
specifier: 'catalog:'
version: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
version: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
js-yaml:
specifier: 'catalog:'
version: 4.1.0
@ -636,7 +636,7 @@ importers:
version: 0.7.0(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.9)
'@tanstack/react-form':
specifier: ^1.23.0
version: 1.23.0(@tanstack/react-start@1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9)))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
version: 1.23.0(@tanstack/react-start@1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9)))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@tanstack/react-query':
specifier: ^5.90.2
version: 5.90.2(react@19.1.1)
@ -660,7 +660,7 @@ importers:
version: 1.130.17(@tanstack/react-query@5.90.2(react@19.1.1))(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.50)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@tanstack/react-start':
specifier: ^1.131.50
version: 1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))
version: 1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))
'@tanstack/react-store':
specifier: ^0.7.7
version: 0.7.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
@ -1012,7 +1012,7 @@ importers:
version: link:../vitest-config
drizzle-orm:
specifier: 'catalog:'
version: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
version: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
lru-cache:
specifier: ^11.1.0
version: 11.1.0
@ -1081,7 +1081,7 @@ importers:
version: 0.3.7(@aws-sdk/credential-provider-web-identity@3.888.0)(zod@3.25.76)
drizzle-orm:
specifier: 'catalog:'
version: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
version: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
glob:
specifier: ^11.0.3
version: 11.0.3
@ -1100,6 +1100,10 @@ importers:
zod:
specifier: 'catalog:'
version: 3.25.76
devDependencies:
'@types/bun':
specifier: ^1.2.23
version: 1.2.23(@types/react@19.1.13)
packages/data-source:
dependencies:
@ -1184,10 +1188,10 @@ importers:
version: 0.31.4
drizzle-orm:
specifier: 'catalog:'
version: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
version: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
drizzle-zod:
specifier: ^0.8.3
version: 0.8.3(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(zod@3.25.76)
version: 0.8.3(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(zod@3.25.76)
lru-cache:
specifier: ^11.2.1
version: 11.2.1
@ -6233,6 +6237,9 @@ packages:
'@types/bun@1.2.21':
resolution: {integrity: sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A==}
'@types/bun@1.2.23':
resolution: {integrity: sha512-le8ueOY5b6VKYf19xT3McVbXqLqmxzPXHsQT/q9JHgikJ2X22wyTW3g3ohz2ZMnp7dod6aduIiq8A14Xyimm0A==}
'@types/canvas-confetti@1.9.0':
resolution: {integrity: sha512-aBGj/dULrimR1XDZLtG9JwxX1b4HPRF6CX9Yfwh3NvstZEm1ZL7RBnel4keCPSqs1ANRu1u2Aoz9R+VmtjYuTg==}
@ -7040,6 +7047,11 @@ packages:
peerDependencies:
'@types/react': ^19
bun-types@1.2.23:
resolution: {integrity: sha512-R9f0hKAZXgFU3mlrA0YpE/fiDvwV0FT9rORApt2aQVWSuJDzZOyB5QLc0N/4HF57CS8IXJ6+L5E4W1bW6NS2Aw==}
peerDependencies:
'@types/react': ^19
bundle-name@4.1.0:
resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
engines: {node: '>=18'}
@ -18371,7 +18383,7 @@ snapshots:
- solid-js
- utf-8-validate
'@tanstack/react-form@1.23.0(@tanstack/react-start@1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9)))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
'@tanstack/react-form@1.23.0(@tanstack/react-start@1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9)))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
dependencies:
'@tanstack/form-core': 1.23.0
'@tanstack/react-store': 0.7.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
@ -18379,7 +18391,7 @@ snapshots:
devalue: 5.3.2
react: 19.1.1
optionalDependencies:
'@tanstack/react-start': 1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))
'@tanstack/react-start': 1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))
transitivePeerDependencies:
- react-dom
@ -18453,9 +18465,9 @@ snapshots:
tiny-invariant: 1.3.3
tiny-warning: 1.0.3
'@tanstack/react-start-plugin@1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))':
'@tanstack/react-start-plugin@1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))':
dependencies:
'@tanstack/start-plugin-core': 1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))
'@tanstack/start-plugin-core': 1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))
'@vitejs/plugin-react': 5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))
pathe: 2.0.3
vite: 7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)
@ -18505,10 +18517,10 @@ snapshots:
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
'@tanstack/react-start@1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))':
'@tanstack/react-start@1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))':
dependencies:
'@tanstack/react-start-client': 1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@tanstack/react-start-plugin': 1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))
'@tanstack/react-start-plugin': 1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@vitejs/plugin-react@5.0.3(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))
'@tanstack/react-start-server': 1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@tanstack/start-server-functions-client': 1.131.50(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))
'@tanstack/start-server-functions-server': 1.131.2(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))
@ -18672,7 +18684,7 @@ snapshots:
tiny-invariant: 1.3.3
tiny-warning: 1.0.3
'@tanstack/start-plugin-core@1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))':
'@tanstack/start-plugin-core@1.131.50(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(@tanstack/react-router@1.131.50(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(webpack@5.99.9(esbuild@0.25.9))':
dependencies:
'@babel/code-frame': 7.26.2
'@babel/core': 7.28.4
@ -18688,7 +18700,7 @@ snapshots:
babel-dead-code-elimination: 1.0.10
cheerio: 1.1.2
h3: 1.13.0
nitropack: 2.12.5(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))
nitropack: 2.12.5(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))
pathe: 2.0.3
ufo: 1.6.1
vite: 7.1.4(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)
@ -19183,6 +19195,12 @@ snapshots:
transitivePeerDependencies:
- '@types/react'
'@types/bun@1.2.23(@types/react@19.1.13)':
dependencies:
bun-types: 1.2.23(@types/react@19.1.13)
transitivePeerDependencies:
- '@types/react'
'@types/canvas-confetti@1.9.0': {}
'@types/caseless@0.12.5': {}
@ -19289,7 +19307,7 @@ snapshots:
'@types/node-fetch@2.6.12':
dependencies:
'@types/node': 18.19.124
'@types/node': 22.18.1
form-data: 4.0.4
'@types/node@16.9.1': {}
@ -19356,7 +19374,7 @@ snapshots:
'@types/request@2.48.12':
dependencies:
'@types/caseless': 0.12.5
'@types/node': 24.3.1
'@types/node': 22.18.1
'@types/tough-cookie': 4.0.5
form-data: 2.5.3
@ -20214,6 +20232,11 @@ snapshots:
'@types/node': 24.3.1
'@types/react': 19.1.13
bun-types@1.2.23(@types/react@19.1.13):
dependencies:
'@types/node': 22.18.1
'@types/react': 19.1.13
bundle-name@4.1.0:
dependencies:
run-applescript: 7.0.0
@ -20730,9 +20753,9 @@ snapshots:
dayjs@1.11.18: {}
db0@0.3.2(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(mysql2@3.14.1):
db0@0.3.2(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(mysql2@3.14.1):
optionalDependencies:
drizzle-orm: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
drizzle-orm: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
mysql2: 3.14.1
debug@2.6.9:
@ -20907,18 +20930,18 @@ snapshots:
transitivePeerDependencies:
- supports-color
drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7):
drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7):
optionalDependencies:
'@opentelemetry/api': 1.9.0
'@types/pg': 8.15.4
bun-types: 1.2.21(@types/react@19.1.13)
bun-types: 1.2.23(@types/react@19.1.13)
mysql2: 3.14.1
pg: 8.16.3
postgres: 3.4.7
drizzle-zod@0.8.3(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(zod@3.25.76):
drizzle-zod@0.8.3(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(zod@3.25.76):
dependencies:
drizzle-orm: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
drizzle-orm: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7)
zod: 3.25.76
dt-sql-parser@4.3.1(antlr4ng-cli@1.0.7):
@ -23869,7 +23892,7 @@ snapshots:
- babel-plugin-macros
optional: true
nitropack@2.12.5(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13)):
nitropack@2.12.5(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(mysql2@3.14.1)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13)):
dependencies:
'@cloudflare/kv-asset-handler': 0.4.0
'@rollup/plugin-alias': 5.1.1(rollup@4.50.0)
@ -23890,7 +23913,7 @@ snapshots:
cookie-es: 2.0.0
croner: 9.1.0
crossws: 0.3.5
db0: 0.3.2(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(mysql2@3.14.1)
db0: 0.3.2(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(mysql2@3.14.1)
defu: 6.1.4
destr: 2.0.5
dot-prop: 9.0.0
@ -23936,7 +23959,7 @@ snapshots:
unenv: 2.0.0-rc.20
unimport: 5.2.0
unplugin-utils: 0.3.0
unstorage: 1.17.1(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(db0@0.3.2(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(mysql2@3.14.1))(ioredis@5.7.0)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))
unstorage: 1.17.1(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(db0@0.3.2(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(mysql2@3.14.1))(ioredis@5.7.0)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13))
untyped: 2.0.0
unwasm: 0.3.11
youch: 4.1.0-beta.8
@ -26473,7 +26496,7 @@ snapshots:
picomatch: 4.0.3
webpack-virtual-modules: 0.6.2
unstorage@1.17.1(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(db0@0.3.2(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(mysql2@3.14.1))(ioredis@5.7.0)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13)):
unstorage@1.17.1(@azure/identity@4.10.2)(@azure/storage-blob@12.26.0)(db0@0.3.2(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(mysql2@3.14.1))(ioredis@5.7.0)(uploadthing@7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13)):
dependencies:
anymatch: 3.1.3
chokidar: 4.0.3
@ -26486,7 +26509,7 @@ snapshots:
optionalDependencies:
'@azure/identity': 4.10.2
'@azure/storage-blob': 12.26.0
db0: 0.3.2(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.21(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(mysql2@3.14.1)
db0: 0.3.2(drizzle-orm@0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7))(mysql2@3.14.1)
ioredis: 5.7.0
uploadthing: 7.7.4(express@5.1.0)(h3@1.15.4)(next@14.2.30(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.1))(tailwindcss@4.1.13)