From 0bf12c1ab1288c07bc0b56c4606783b726c42b1e Mon Sep 17 00:00:00 2001 From: Nikhil Sonti Date: Thu, 26 Feb 2026 14:48:13 -0800 Subject: [PATCH 1/2] feat: replace pi-mono filesystem tools with native Bun/Node.js implementation Remove @mariozechner/pi-coding-agent and @mariozechner/pi-agent-core dependencies that caused bun compile issues (tree traversal, package.json resolution). Reimplement all 7 filesystem tools (read, write, edit, bash, grep, find, ls) using only Bun and Node.js built-in libraries. - No external binary dependencies (no ripgrep, fd, etc.) - Cross-platform: Linux, macOS, Windows - 107 tests covering all tools and utilities - Pure JS grep/find using Bun.Glob and async directory walking Co-Authored-By: Claude Opus 4.6 --- apps/server/package.json | 2 - .../src/agent/tool-loop/ai-sdk-agent.ts | 2 +- .../filesystem-tools/pi-tool-adapter.ts | 133 ------ apps/server/src/tools/filesystem/bash.ts | 84 ++++ .../src/tools/filesystem/build-toolset.ts | 20 + apps/server/src/tools/filesystem/edit.ts | 134 ++++++ apps/server/src/tools/filesystem/find.ts | 69 +++ apps/server/src/tools/filesystem/grep.ts | 219 +++++++++ apps/server/src/tools/filesystem/ls.ts | 82 ++++ apps/server/src/tools/filesystem/read.ts | 82 ++++ apps/server/src/tools/filesystem/utils.ts | 312 +++++++++++++ apps/server/src/tools/filesystem/write.ts | 29 ++ .../tests/tools/filesystem/bash.test.ts | 98 ++++ .../tests/tools/filesystem/edit.test.ts | 181 ++++++++ .../tests/tools/filesystem/find.test.ts | 136 ++++++ .../tests/tools/filesystem/grep.test.ts | 154 +++++++ apps/server/tests/tools/filesystem/ls.test.ts | 107 +++++ .../tests/tools/filesystem/read.test.ts | 132 ++++++ .../tests/tools/filesystem/utils.test.ts | 237 ++++++++++ .../tests/tools/filesystem/write.test.ts | 86 ++++ bun.lock | 418 +----------------- 21 files changed, 2170 insertions(+), 547 deletions(-) delete mode 100644 apps/server/src/agent/tool-loop/filesystem-tools/pi-tool-adapter.ts create mode 100644 apps/server/src/tools/filesystem/bash.ts create mode 100644 apps/server/src/tools/filesystem/build-toolset.ts create mode 100644 apps/server/src/tools/filesystem/edit.ts create mode 100644 apps/server/src/tools/filesystem/find.ts create mode 100644 apps/server/src/tools/filesystem/grep.ts create mode 100644 apps/server/src/tools/filesystem/ls.ts create mode 100644 apps/server/src/tools/filesystem/read.ts create mode 100644 apps/server/src/tools/filesystem/utils.ts create mode 100644 apps/server/src/tools/filesystem/write.ts create mode 100644 apps/server/tests/tools/filesystem/bash.test.ts create mode 100644 apps/server/tests/tools/filesystem/edit.test.ts create mode 100644 apps/server/tests/tools/filesystem/find.test.ts create mode 100644 apps/server/tests/tools/filesystem/grep.test.ts create mode 100644 apps/server/tests/tools/filesystem/ls.test.ts create mode 100644 apps/server/tests/tools/filesystem/read.test.ts create mode 100644 apps/server/tests/tools/filesystem/utils.test.ts create mode 100644 apps/server/tests/tools/filesystem/write.test.ts diff --git a/apps/server/package.json b/apps/server/package.json index aa9081e3..24fc0929 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -55,8 +55,6 @@ "@hono/mcp": "^0.2.3", "@hono/node-server": "^1.19.6", "@hono/zod-validator": "^0.4.3", - "@mariozechner/pi-agent-core": "^0.54.2", - "@mariozechner/pi-coding-agent": "^0.54.2", "@modelcontextprotocol/sdk": "^1.25.2", "@openrouter/ai-sdk-provider": "^2.2.3", "@sentry/bun": "^10.31.0", diff --git a/apps/server/src/agent/tool-loop/ai-sdk-agent.ts b/apps/server/src/agent/tool-loop/ai-sdk-agent.ts index 86aed516..6c28bd1d 100644 --- a/apps/server/src/agent/tool-loop/ai-sdk-agent.ts +++ b/apps/server/src/agent/tool-loop/ai-sdk-agent.ts @@ -4,11 +4,11 @@ import { stepCountIs, ToolLoopAgent, type UIMessage } from 'ai' import type { Browser } from '../../browser/browser' import type { KlavisClient } from '../../lib/clients/klavis/klavis-client' import { logger } from '../../lib/logger' +import { buildFilesystemToolSet } from '../../tools/filesystem/build-toolset' import type { ToolRegistry } from '../../tools/tool-registry' import { buildSystemPrompt } from '../prompt' import type { ResolvedAgentConfig } from '../types' import { createCompactionPrepareStep } from './compaction' -import { buildFilesystemToolSet } from './filesystem-tools/pi-tool-adapter' import { buildMcpServerSpecs, createMcpClients } from './mcp-builder' import { createLanguageModel } from './provider-factory' import { buildBrowserToolSet } from './tool-adapter' diff --git a/apps/server/src/agent/tool-loop/filesystem-tools/pi-tool-adapter.ts b/apps/server/src/agent/tool-loop/filesystem-tools/pi-tool-adapter.ts deleted file mode 100644 index 092e8afe..00000000 --- a/apps/server/src/agent/tool-loop/filesystem-tools/pi-tool-adapter.ts +++ /dev/null @@ -1,133 +0,0 @@ -import type { LanguageModelV2ToolResultOutput } from '@ai-sdk/provider' -import type { AgentTool, AgentToolResult } from '@mariozechner/pi-agent-core' -import { - createBashTool, - createEditTool, - createFindTool, - createGrepTool, - createLsTool, - createReadTool, - createWriteTool, -} from '@mariozechner/pi-coding-agent' -import { jsonSchema, type ToolSet, tool } from 'ai' -import { logger } from '../../../lib/logger' -import { metrics } from '../../../lib/metrics' - -type PiContent = AgentToolResult['content'] - -function piContentToModelOutput( - content: PiContent, -): LanguageModelV2ToolResultOutput { - const hasImages = content.some((c) => c.type === 'image') - - if (!hasImages) { - const text = content - .filter( - (c): c is PiContent[number] & { type: 'text' } => c.type === 'text', - ) - .map((c) => c.text) - .join('\n') - return { type: 'text', value: text || 'Success' } - } - - return { - type: 'content', - value: content.map((c) => { - if (c.type === 'text') { - return { type: 'text' as const, text: c.text } - } - return { - type: 'media' as const, - data: c.data, - mediaType: c.mimeType, - } - }), - } -} - -// biome-ignore lint/suspicious/noExplicitAny: AgentTool is contravariant on TParameters — each createXxxTool returns a specific generic that can't assign to AgentTool without widening -function createAllTools(cwd: string): Record> { - return { - read: createReadTool(cwd), - bash: createBashTool(cwd), - edit: createEditTool(cwd), - write: createWriteTool(cwd), - grep: createGrepTool(cwd), - find: createFindTool(cwd), - ls: createLsTool(cwd), - } -} - -export function buildFilesystemToolSet(cwd: string): ToolSet { - const piTools = createAllTools(cwd) - const toolSet: ToolSet = {} - - for (const [name, piTool] of Object.entries(piTools)) { - const prefixedName = `filesystem_${name}` - - toolSet[prefixedName] = tool({ - description: piTool.description, - inputSchema: jsonSchema( - JSON.parse(JSON.stringify(piTool.parameters)) as Parameters< - typeof jsonSchema - >[0], - ), - execute: async (params) => { - const startTime = performance.now() - try { - const result = await piTool.execute(crypto.randomUUID(), params) - - metrics.log('tool_executed', { - tool_name: prefixedName, - duration_ms: Math.round(performance.now() - startTime), - success: true, - }) - - return { content: result.content, isError: false } - } catch (error) { - const errorText = - error instanceof Error ? error.message : String(error) - - logger.error('Filesystem tool execution failed', { - tool: prefixedName, - error: errorText, - }) - metrics.log('tool_executed', { - tool_name: prefixedName, - duration_ms: Math.round(performance.now() - startTime), - success: false, - error_message: - error instanceof Error ? error.message : 'Unknown error', - }) - - return { - content: [{ type: 'text' as const, text: errorText }], - isError: true, - } - } - }, - toModelOutput: ({ output }) => { - const result = output as { - content: PiContent - isError: boolean - } - if (result.isError) { - const text = result.content - .filter( - (c): c is PiContent[number] & { type: 'text' } => - c.type === 'text', - ) - .map((c) => c.text) - .join('\n') - return { type: 'error-text', value: text } - } - if (!result.content?.length) { - return { type: 'text', value: 'Success' } - } - return piContentToModelOutput(result.content) - }, - }) - } - - return toolSet -} diff --git a/apps/server/src/tools/filesystem/bash.ts b/apps/server/src/tools/filesystem/bash.ts new file mode 100644 index 00000000..4655586d --- /dev/null +++ b/apps/server/src/tools/filesystem/bash.ts @@ -0,0 +1,84 @@ +import { resolve } from 'node:path' +import { tool } from 'ai' +import { z } from 'zod' +import { + DEFAULT_BASH_TIMEOUT, + executeWithMetrics, + toModelOutput, + truncateTail, +} from './utils' + +const TOOL_NAME = 'filesystem_bash' + +function getShellArgs(): [string, string] { + if (process.platform === 'win32') return ['cmd.exe', '/c'] + return [process.env.SHELL || '/bin/sh', '-c'] +} + +export function createBashTool(cwd: string) { + return tool({ + description: + 'Execute a shell command and return its output. Commands run in a shell (sh/bash on Unix, cmd on Windows). Output is truncated to the last 2000 lines if too large.', + inputSchema: z.object({ + command: z.string().describe('Shell command to execute'), + timeout: z + .number() + .optional() + .describe(`Timeout in seconds (default: ${DEFAULT_BASH_TIMEOUT})`), + }), + execute: (params) => + executeWithMetrics(TOOL_NAME, async () => { + const [shell, flag] = getShellArgs() + const timeoutMs = (params.timeout || DEFAULT_BASH_TIMEOUT) * 1000 + const resolvedCwd = resolve(cwd) + + const proc = Bun.spawn([shell, flag, params.command], { + cwd: resolvedCwd, + stdout: 'pipe', + stderr: 'pipe', + env: { ...process.env }, + }) + + let timedOut = false + const timer = setTimeout(() => { + timedOut = true + proc.kill() + }, timeoutMs) + + const [stdoutText, stderrText] = await Promise.all([ + new Response(proc.stdout).text(), + new Response(proc.stderr).text(), + ]) + + const exitCode = await proc.exited + clearTimeout(timer) + + if (timedOut) { + let output = stdoutText + if (stderrText) output += (output ? '\n' : '') + stderrText + const truncated = truncateTail(output) + return { + text: `Command timed out after ${params.timeout || DEFAULT_BASH_TIMEOUT}s\n\n${truncated.content}`, + isError: true, + } + } + + let output = stdoutText + if (stderrText) output += (output ? '\n' : '') + stderrText + + const truncated = truncateTail(output) + let result = truncated.content + if (truncated.truncated) { + result = `(Output truncated. Showing last ${truncated.keptLines} of ${truncated.totalLines} lines)\n${result}` + } + + if (exitCode !== 0) { + result += `\n\n[Exit code: ${exitCode}]` + return { text: result, isError: true } + } + + return { text: result || '(no output)' } + }), + toModelOutput, + }) +} diff --git a/apps/server/src/tools/filesystem/build-toolset.ts b/apps/server/src/tools/filesystem/build-toolset.ts new file mode 100644 index 00000000..f426ab1c --- /dev/null +++ b/apps/server/src/tools/filesystem/build-toolset.ts @@ -0,0 +1,20 @@ +import type { ToolSet } from 'ai' +import { createBashTool } from './bash' +import { createEditTool } from './edit' +import { createFindTool } from './find' +import { createGrepTool } from './grep' +import { createLsTool } from './ls' +import { createReadTool } from './read' +import { createWriteTool } from './write' + +export function buildFilesystemToolSet(cwd: string): ToolSet { + return { + filesystem_read: createReadTool(cwd), + filesystem_write: createWriteTool(cwd), + filesystem_edit: createEditTool(cwd), + filesystem_bash: createBashTool(cwd), + filesystem_grep: createGrepTool(cwd), + filesystem_find: createFindTool(cwd), + filesystem_ls: createLsTool(cwd), + } +} diff --git a/apps/server/src/tools/filesystem/edit.ts b/apps/server/src/tools/filesystem/edit.ts new file mode 100644 index 00000000..3b68eb82 --- /dev/null +++ b/apps/server/src/tools/filesystem/edit.ts @@ -0,0 +1,134 @@ +import { readFile, writeFile } from 'node:fs/promises' +import { resolve } from 'node:path' +import { tool } from 'ai' +import { z } from 'zod' +import { + detectLineEnding, + executeWithMetrics, + normalizeToLF, + restoreLineEndings, + stripBom, + toModelOutput, +} from './utils' + +const TOOL_NAME = 'filesystem_edit' + +function countOccurrences(content: string, search: string): number { + let count = 0 + let pos = 0 + while (true) { + pos = content.indexOf(search, pos) + if (pos === -1) break + count++ + pos += search.length + } + return count +} + +function fuzzyReplace( + content: string, + oldStr: string, + newStr: string, +): string | null { + const contentLines = content.split('\n') + const searchLines = oldStr.split('\n') + const trimmedSearch = searchLines.map((l) => l.trim()) + + let matchCount = 0 + let matchStartLine = -1 + + for (let i = 0; i <= contentLines.length - searchLines.length; i++) { + let allMatch = true + for (let j = 0; j < searchLines.length; j++) { + if (contentLines[i + j].trim() !== trimmedSearch[j]) { + allMatch = false + break + } + } + if (allMatch) { + matchCount++ + if (matchCount === 1) matchStartLine = i + } + } + + if (matchCount === 0) return null + if (matchCount > 1) { + throw new Error( + `Whitespace-tolerant match found ${matchCount} occurrences. Add more context to make the match unique.`, + ) + } + + const before = contentLines.slice(0, matchStartLine) + const after = contentLines.slice(matchStartLine + searchLines.length) + return [...before, ...newStr.split('\n'), ...after].join('\n') +} + +function generateDiff(oldStr: string, newStr: string): string { + const oldLines = oldStr.split('\n') + const newLines = newStr.split('\n') + const lines: string[] = [] + for (const line of oldLines) lines.push(`- ${line}`) + for (const line of newLines) lines.push(`+ ${line}`) + return lines.join('\n') +} + +export function createEditTool(cwd: string) { + return tool({ + description: + 'Make a targeted edit to a file by replacing an exact string match. The old_string must match exactly one location in the file. If exact match fails, a whitespace-tolerant match is attempted.', + inputSchema: z.object({ + path: z + .string() + .describe('File path (relative to working directory or absolute)'), + old_string: z.string().describe('Exact text to find in the file'), + new_string: z.string().describe('Replacement text'), + }), + execute: (params) => + executeWithMetrics(TOOL_NAME, async () => { + const resolved = resolve(cwd, params.path) + const raw = await readFile(resolved, 'utf-8') + + const { content: noBom, hasBom } = stripBom(raw) + const lineEnding = detectLineEnding(noBom) + const content = normalizeToLF(noBom) + const oldNorm = normalizeToLF(params.old_string) + const newNorm = normalizeToLF(params.new_string) + + if (oldNorm === newNorm) { + return { + text: 'old_string and new_string are identical — no change needed.', + isError: true, + } + } + + let updated: string + const exactCount = countOccurrences(content, oldNorm) + + if (exactCount === 1) { + updated = content.replace(oldNorm, newNorm) + } else if (exactCount > 1) { + return { + text: `Found ${exactCount} exact occurrences of old_string. Add more surrounding context to make the match unique.`, + isError: true, + } + } else { + const fuzzyResult = fuzzyReplace(content, oldNorm, newNorm) + if (fuzzyResult === null) { + return { + text: 'old_string not found in file (exact and whitespace-tolerant match both failed).', + isError: true, + } + } + updated = fuzzyResult + } + + let finalContent = restoreLineEndings(updated, lineEnding) + if (hasBom) finalContent = `\uFEFF${finalContent}` + await writeFile(resolved, finalContent, 'utf-8') + + const diff = generateDiff(params.old_string, params.new_string) + return { text: `Applied edit to ${params.path}\n\n${diff}` } + }), + toModelOutput, + }) +} diff --git a/apps/server/src/tools/filesystem/find.ts b/apps/server/src/tools/filesystem/find.ts new file mode 100644 index 00000000..0ecd5239 --- /dev/null +++ b/apps/server/src/tools/filesystem/find.ts @@ -0,0 +1,69 @@ +import { resolve } from 'node:path' +import { tool } from 'ai' +import { z } from 'zod' +import { + DEFAULT_FIND_LIMIT, + executeWithMetrics, + toModelOutput, + walkFiles, +} from './utils' + +const TOOL_NAME = 'filesystem_find' + +export function createFindTool(cwd: string) { + return tool({ + description: + 'Find files matching a glob pattern. Searches recursively, skipping common build directories (node_modules, .git, dist, etc.). Returns relative file paths.', + inputSchema: z.object({ + pattern: z + .string() + .describe( + 'Glob pattern (e.g., "*.ts", "**/*.json", "src/**/*.test.ts")', + ), + path: z + .string() + .optional() + .describe('Directory to search (default: working directory)'), + limit: z + .number() + .optional() + .describe(`Maximum results (default: ${DEFAULT_FIND_LIMIT})`), + }), + execute: (params) => + executeWithMetrics(TOOL_NAME, async () => { + const searchPath = resolve(cwd, params.path || '.') + const limit = params.limit || DEFAULT_FIND_LIMIT + + let effectivePattern = params.pattern + if ( + !effectivePattern.includes('/') && + !effectivePattern.includes('**') + ) { + effectivePattern = `**/${effectivePattern}` + } + + const glob = new Bun.Glob(effectivePattern) + const matches: string[] = [] + + for await (const relPath of walkFiles(searchPath, searchPath)) { + if (glob.match(relPath)) { + matches.push(relPath) + if (matches.length >= limit) break + } + } + + if (matches.length === 0) { + return { text: `No files matching "${params.pattern}" found.` } + } + + matches.sort() + let result = matches.join('\n') + if (matches.length >= limit) { + result += `\n\n(Showing first ${limit} results. Use limit=${limit * 2} to see more.)` + } + + return { text: result } + }), + toModelOutput, + }) +} diff --git a/apps/server/src/tools/filesystem/grep.ts b/apps/server/src/tools/filesystem/grep.ts new file mode 100644 index 00000000..82860849 --- /dev/null +++ b/apps/server/src/tools/filesystem/grep.ts @@ -0,0 +1,219 @@ +import { readFile, stat } from 'node:fs/promises' +import { join, resolve } from 'node:path' +import { tool } from 'ai' +import { z } from 'zod' +import { + DEFAULT_GREP_LIMIT, + executeWithMetrics, + GREP_MAX_LINE_LENGTH, + isBinaryPath, + MAX_GREP_FILE_SIZE, + toModelOutput, + truncateLine, + walkFiles, +} from './utils' + +const TOOL_NAME = 'filesystem_grep' + +interface GrepMatch { + file: string + lineNum: number + line: string + isMatch: boolean +} + +function searchFileLines( + filePath: string, + lines: string[], + regex: RegExp, + context: number, + maxMatches: number, +): GrepMatch[] { + const matchIndices: number[] = [] + for (let i = 0; i < lines.length && matchIndices.length < maxMatches; i++) { + if (regex.test(lines[i])) { + matchIndices.push(i) + } + } + + if (matchIndices.length === 0) return [] + + const included = new Set() + for (const idx of matchIndices) { + for ( + let i = Math.max(0, idx - context); + i <= Math.min(lines.length - 1, idx + context); + i++ + ) { + included.add(i) + } + } + + const matchSet = new Set(matchIndices) + return [...included] + .sort((a, b) => a - b) + .map((i) => ({ + file: filePath, + lineNum: i + 1, + line: lines[i], + isMatch: matchSet.has(i), + })) +} + +function formatMatches(matches: GrepMatch[], context: number): string { + const lines: string[] = [] + let prevFile = '' + let prevLineNum = -1 + + for (const m of matches) { + if (m.file !== prevFile) { + if (lines.length > 0) lines.push('') + prevFile = m.file + prevLineNum = -1 + } + + if (context > 0 && prevLineNum !== -1 && m.lineNum > prevLineNum + 1) { + lines.push('--') + } + + const sep = m.isMatch ? ':' : '-' + const displayLine = truncateLine(m.line, GREP_MAX_LINE_LENGTH) + lines.push(`${m.file}${sep}${m.lineNum}${sep}${displayLine}`) + prevLineNum = m.lineNum + } + + return lines.join('\n') +} + +export function createGrepTool(cwd: string) { + return tool({ + description: + 'Search file contents using a regular expression. Returns matching lines with file paths and line numbers. Searches recursively, skipping binary files and common build directories (node_modules, .git, dist, etc.).', + inputSchema: z.object({ + pattern: z + .string() + .describe( + 'Search pattern (regex by default, or literal string if literal=true)', + ), + path: z + .string() + .optional() + .describe('Directory or file to search (default: working directory)'), + glob: z + .string() + .optional() + .describe('Filter files by glob pattern (e.g., "*.ts", "*.{js,jsx}")'), + ignore_case: z.boolean().optional().describe('Case-insensitive search'), + literal: z + .boolean() + .optional() + .describe('Treat pattern as a literal string, not regex'), + context: z + .number() + .optional() + .describe('Lines of context before and after each match'), + limit: z + .number() + .optional() + .describe(`Maximum matches to return (default: ${DEFAULT_GREP_LIMIT})`), + }), + execute: (params) => + executeWithMetrics(TOOL_NAME, async () => { + const searchPath = resolve(cwd, params.path || '.') + const limit = params.limit || DEFAULT_GREP_LIMIT + const context = params.context || 0 + + const escapedPattern = params.literal + ? params.pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + : params.pattern + + let regex: RegExp + try { + regex = new RegExp(escapedPattern, params.ignore_case ? 'i' : '') + } catch (_e) { + return { + text: `Invalid regex pattern: ${params.pattern}`, + isError: true, + } + } + + let globMatcher: InstanceType | null = null + if (params.glob) { + let effectiveGlob = params.glob + if (!effectiveGlob.includes('/') && !effectiveGlob.includes('**')) { + effectiveGlob = `**/${effectiveGlob}` + } + globMatcher = new Bun.Glob(effectiveGlob) + } + + // Check if searching a single file + const pathStat = await stat(searchPath) + const allMatches: GrepMatch[] = [] + let totalMatchCount = 0 + + if (pathStat.isFile()) { + const content = await readFile(searchPath, 'utf-8') + const lines = content.split('\n') + const relPath = params.path || searchPath + const fileMatches = searchFileLines( + relPath, + lines, + regex, + context, + limit, + ) + allMatches.push(...fileMatches) + totalMatchCount = fileMatches.filter((m) => m.isMatch).length + } else { + for await (const relPath of walkFiles(searchPath, searchPath)) { + if (isBinaryPath(relPath)) continue + if (globMatcher && !globMatcher.match(relPath)) continue + + const fullPath = join(searchPath, relPath) + try { + const fileStat = await stat(fullPath) + if (fileStat.size > MAX_GREP_FILE_SIZE) continue + } catch { + continue + } + + let content: string + try { + content = await readFile(fullPath, 'utf-8') + } catch { + continue + } + + const lines = content.split('\n') + const remaining = limit - totalMatchCount + if (remaining <= 0) break + + const fileMatches = searchFileLines( + relPath, + lines, + regex, + context, + remaining, + ) + const matchCount = fileMatches.filter((m) => m.isMatch).length + totalMatchCount += matchCount + allMatches.push(...fileMatches) + + if (totalMatchCount >= limit) break + } + } + + if (allMatches.length === 0) { + return { text: 'No matches found.' } + } + + let result = formatMatches(allMatches, context) + if (totalMatchCount >= limit) { + result += `\n\n(Showing first ${limit} matches. Use limit=${limit * 2} to see more.)` + } + + return { text: result } + }), + toModelOutput, + }) +} diff --git a/apps/server/src/tools/filesystem/ls.ts b/apps/server/src/tools/filesystem/ls.ts new file mode 100644 index 00000000..34429ebe --- /dev/null +++ b/apps/server/src/tools/filesystem/ls.ts @@ -0,0 +1,82 @@ +import { readdir, stat } from 'node:fs/promises' +import { join, resolve } from 'node:path' +import { tool } from 'ai' +import { z } from 'zod' +import { DEFAULT_LS_LIMIT, executeWithMetrics, toModelOutput } from './utils' + +const TOOL_NAME = 'filesystem_ls' + +function formatSize(bytes: number): string { + if (bytes < 1024) return `${bytes}B` + if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB` + return `${(bytes / (1024 * 1024)).toFixed(1)}MB` +} + +export function createLsTool(cwd: string) { + return tool({ + description: + 'List directory contents. Shows directories (with trailing /) first, then files with sizes. Entries are sorted alphabetically.', + inputSchema: z.object({ + path: z + .string() + .optional() + .describe('Directory path (default: working directory)'), + limit: z + .number() + .optional() + .describe(`Maximum entries to return (default: ${DEFAULT_LS_LIMIT})`), + }), + execute: (params) => + executeWithMetrics(TOOL_NAME, async () => { + const resolved = resolve(cwd, params.path || '.') + const limit = params.limit || DEFAULT_LS_LIMIT + const entries = await readdir(resolved, { withFileTypes: true }) + + const dirs: string[] = [] + const files: Array<{ name: string; size: number }> = [] + + for (const entry of entries) { + if (entry.isDirectory()) { + dirs.push(entry.name) + } else { + try { + const info = await stat(join(resolved, entry.name)) + files.push({ name: entry.name, size: info.size }) + } catch { + files.push({ name: entry.name, size: 0 }) + } + } + } + + dirs.sort((a, b) => + a.localeCompare(b, undefined, { sensitivity: 'base' }), + ) + files.sort((a, b) => + a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }), + ) + + const lines: string[] = [] + for (const dir of dirs) { + if (lines.length >= limit) break + lines.push(`${dir}/`) + } + for (const file of files) { + if (lines.length >= limit) break + lines.push(`${file.name} (${formatSize(file.size)})`) + } + + if (lines.length === 0) { + return { text: '(empty directory)' } + } + + let result = lines.join('\n') + const total = dirs.length + files.length + if (total > limit) { + result += `\n\n(Showing ${limit} of ${total} entries. Use limit=${limit * 2} to see more.)` + } + + return { text: result } + }), + toModelOutput, + }) +} diff --git a/apps/server/src/tools/filesystem/read.ts b/apps/server/src/tools/filesystem/read.ts new file mode 100644 index 00000000..dcc32a28 --- /dev/null +++ b/apps/server/src/tools/filesystem/read.ts @@ -0,0 +1,82 @@ +import { readFile } from 'node:fs/promises' +import { extname, resolve } from 'node:path' +import { tool } from 'ai' +import { z } from 'zod' +import { + executeWithMetrics, + IMAGE_EXTENSIONS, + IMAGE_MIME_TYPES, + toModelOutput, + truncateHead, +} from './utils' + +const TOOL_NAME = 'filesystem_read' + +export function createReadTool(cwd: string) { + return tool({ + description: + 'Read a file from the filesystem. Returns text content with line numbers, or image data for image files. Use offset and limit to paginate through large files.', + inputSchema: z.object({ + path: z + .string() + .describe('File path (relative to working directory or absolute)'), + offset: z + .number() + .optional() + .describe('Starting line number (1-indexed)'), + limit: z.number().optional().describe('Maximum number of lines to read'), + }), + execute: (params) => + executeWithMetrics(TOOL_NAME, async () => { + const resolved = resolve(cwd, params.path) + const ext = extname(resolved).toLowerCase() + + if (IMAGE_EXTENSIONS.has(ext)) { + const buffer = await readFile(resolved) + const mimeType = IMAGE_MIME_TYPES[ext] || 'application/octet-stream' + return { + text: `Image: ${params.path} (${buffer.byteLength} bytes)`, + images: [{ data: buffer.toString('base64'), mimeType }], + } + } + + const content = await readFile(resolved, 'utf-8') + const allLines = content.split('\n') + const totalLines = allLines.length + + const startIdx = params.offset ? Math.max(0, params.offset - 1) : 0 + if (startIdx >= totalLines) { + return { + text: `File has ${totalLines} lines. Offset ${params.offset} is beyond end of file.`, + } + } + + let selected = allLines.slice(startIdx) + if (params.limit && params.limit < selected.length) { + selected = selected.slice(0, params.limit) + } + + const truncated = truncateHead(selected.join('\n')) + const displayLines = truncated.content.split('\n') + const endLineNum = startIdx + displayLines.length + const width = String(endLineNum).length + + const numbered = displayLines + .map((line, i) => { + const num = String(startIdx + i + 1).padStart(width) + return `${num} | ${line}` + }) + .join('\n') + + let result = numbered + if (truncated.truncated) { + result += `\n\n(Showing ${displayLines.length} of ${totalLines} lines. Use offset=${startIdx + displayLines.length + 1} to continue reading.)` + } else if (startIdx > 0) { + result += `\n\n(Showing lines ${startIdx + 1}-${endLineNum} of ${totalLines})` + } + + return { text: result } + }), + toModelOutput, + }) +} diff --git a/apps/server/src/tools/filesystem/utils.ts b/apps/server/src/tools/filesystem/utils.ts new file mode 100644 index 00000000..21ba3fa3 --- /dev/null +++ b/apps/server/src/tools/filesystem/utils.ts @@ -0,0 +1,312 @@ +import type { Dirent } from 'node:fs' +import { readdir } from 'node:fs/promises' +import { join, relative } from 'node:path' +import { logger } from '../../lib/logger' +import { metrics } from '../../lib/metrics' + +export const MAX_LINES = 2000 +export const MAX_BYTES = 50 * 1024 +export const GREP_MAX_LINE_LENGTH = 500 +export const DEFAULT_GREP_LIMIT = 100 +export const DEFAULT_FIND_LIMIT = 1000 +export const DEFAULT_LS_LIMIT = 500 +export const DEFAULT_BASH_TIMEOUT = 120 +export const MAX_GREP_FILE_SIZE = 2 * 1024 * 1024 + +export interface FilesystemToolResult { + text: string + isError?: boolean + images?: Array<{ data: string; mimeType: string }> +} + +export interface TruncationResult { + content: string + truncated: boolean + totalLines: number + keptLines: number +} + +export function truncateHead( + content: string, + maxLines = MAX_LINES, + maxBytes = MAX_BYTES, +): TruncationResult { + const lines = content.split('\n') + const totalLines = lines.length + const kept: string[] = [] + let bytes = 0 + + for (const line of lines) { + const lineBytes = Buffer.byteLength(line, 'utf-8') + 1 + if (kept.length >= maxLines || bytes + lineBytes > maxBytes) { + return { + content: kept.join('\n'), + truncated: true, + totalLines, + keptLines: kept.length, + } + } + kept.push(line) + bytes += lineBytes + } + + return { + content: kept.join('\n'), + truncated: false, + totalLines, + keptLines: kept.length, + } +} + +export function truncateTail( + content: string, + maxLines = MAX_LINES, + maxBytes = MAX_BYTES, +): TruncationResult { + const lines = content.split('\n') + const totalLines = lines.length + const kept: string[] = [] + let bytes = 0 + + for (let i = lines.length - 1; i >= 0; i--) { + const lineBytes = Buffer.byteLength(lines[i], 'utf-8') + 1 + if (kept.length >= maxLines || bytes + lineBytes > maxBytes) { + return { + content: kept.reverse().join('\n'), + truncated: true, + totalLines, + keptLines: kept.length, + } + } + kept.push(lines[i]) + bytes += lineBytes + } + + return { + content: kept.reverse().join('\n'), + truncated: false, + totalLines, + keptLines: kept.length, + } +} + +export function truncateLine( + line: string, + maxChars = GREP_MAX_LINE_LENGTH, +): string { + if (line.length <= maxChars) return line + return `${line.slice(0, maxChars)} [truncated]` +} + +export const IGNORED_DIRS = new Set([ + 'node_modules', + '.git', + 'dist', + 'build', + '.next', + 'coverage', + '__pycache__', + '.venv', + 'venv', + '.tox', + 'target', + '.gradle', + '.idea', + '.vscode', + '.cache', + '.turbo', + '.output', + '.nuxt', + '.svelte-kit', + '.parcel-cache', + '.angular', + '.expo', + '.yarn', + '.pnp', +]) + +const BINARY_EXTENSIONS = new Set([ + '.png', + '.jpg', + '.jpeg', + '.gif', + '.webp', + '.bmp', + '.ico', + '.woff', + '.woff2', + '.ttf', + '.eot', + '.otf', + '.pdf', + '.doc', + '.docx', + '.xls', + '.xlsx', + '.ppt', + '.pptx', + '.zip', + '.tar', + '.gz', + '.bz2', + '.rar', + '.7z', + '.xz', + '.exe', + '.dll', + '.so', + '.dylib', + '.bin', + '.o', + '.a', + '.mp3', + '.mp4', + '.avi', + '.mov', + '.wav', + '.flac', + '.ogg', + '.sqlite', + '.db', + '.wasm', + '.class', + '.pyc', +]) + +export function isBinaryPath(filePath: string): boolean { + const dot = filePath.lastIndexOf('.') + if (dot === -1) return false + return BINARY_EXTENSIONS.has(filePath.slice(dot).toLowerCase()) +} + +export const IMAGE_EXTENSIONS = new Set([ + '.png', + '.jpg', + '.jpeg', + '.gif', + '.webp', + '.bmp', + '.svg', + '.ico', +]) + +export const IMAGE_MIME_TYPES: Record = { + '.png': 'image/png', + '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', + '.gif': 'image/gif', + '.webp': 'image/webp', + '.bmp': 'image/bmp', + '.svg': 'image/svg+xml', + '.ico': 'image/x-icon', +} + +export async function* walkFiles( + dir: string, + baseDir: string, +): AsyncGenerator { + let entries: Dirent[] + try { + entries = (await readdir(dir, { withFileTypes: true })) as Dirent[] + } catch { + return + } + + for (const entry of entries) { + const fullPath = join(dir, entry.name as string) + if (entry.isDirectory()) { + if (IGNORED_DIRS.has(entry.name as string)) continue + yield* walkFiles(fullPath, baseDir) + } else if (entry.isFile() || entry.isSymbolicLink()) { + yield relative(baseDir, fullPath) + } + } +} + +export function toModelOutput({ + output, +}: { + output: unknown + toolCallId: string + input: unknown +}) { + const result = output as FilesystemToolResult + if (result.isError) { + return { type: 'error-text' as const, value: result.text } + } + if (result.images?.length) { + return { + type: 'content' as const, + value: [ + { type: 'text' as const, text: result.text }, + ...result.images.map((img) => ({ + type: 'media' as const, + data: img.data, + mediaType: img.mimeType, + })), + ], + } + } + return { type: 'text' as const, value: result.text || 'Success' } +} + +export function executeWithMetrics( + toolName: string, + fn: () => Promise, +): Promise { + const startTime = performance.now() + return fn().then( + (result) => { + metrics.log('tool_executed', { + tool_name: toolName, + duration_ms: Math.round(performance.now() - startTime), + success: !result.isError, + }) + return result + }, + (error) => { + const errorText = error instanceof Error ? error.message : String(error) + logger.error('Filesystem tool execution failed', { + tool: toolName, + error: errorText, + }) + metrics.log('tool_executed', { + tool_name: toolName, + duration_ms: Math.round(performance.now() - startTime), + success: false, + error_message: errorText, + }) + return { text: errorText, isError: true } + }, + ) +} + +export function stripBom(content: string): { + content: string + hasBom: boolean +} { + if (content.charCodeAt(0) === 0xfeff) { + return { content: content.slice(1), hasBom: true } + } + return { content, hasBom: false } +} + +export function detectLineEnding(content: string): '\r\n' | '\r' | '\n' { + const crlfIdx = content.indexOf('\r\n') + if (crlfIdx !== -1) return '\r\n' + const crIdx = content.indexOf('\r') + if (crIdx !== -1) return '\r' + return '\n' +} + +export function normalizeToLF(content: string): string { + return content.replace(/\r\n/g, '\n').replace(/\r/g, '\n') +} + +export function restoreLineEndings( + content: string, + lineEnding: string, +): string { + if (lineEnding === '\n') return content + return content.replace(/\n/g, lineEnding) +} diff --git a/apps/server/src/tools/filesystem/write.ts b/apps/server/src/tools/filesystem/write.ts new file mode 100644 index 00000000..9fc8992c --- /dev/null +++ b/apps/server/src/tools/filesystem/write.ts @@ -0,0 +1,29 @@ +import { mkdir, writeFile } from 'node:fs/promises' +import { dirname, resolve } from 'node:path' +import { tool } from 'ai' +import { z } from 'zod' +import { executeWithMetrics, toModelOutput } from './utils' + +const TOOL_NAME = 'filesystem_write' + +export function createWriteTool(cwd: string) { + return tool({ + description: + "Create or overwrite a file. Automatically creates parent directories if they don't exist. Use this to create new files or completely replace file contents.", + inputSchema: z.object({ + path: z + .string() + .describe('File path (relative to working directory or absolute)'), + content: z.string().describe('Complete file content to write'), + }), + execute: (params) => + executeWithMetrics(TOOL_NAME, async () => { + const resolved = resolve(cwd, params.path) + await mkdir(dirname(resolved), { recursive: true }) + await writeFile(resolved, params.content, 'utf-8') + const bytes = Buffer.byteLength(params.content, 'utf-8') + return { text: `Wrote ${bytes} bytes to ${params.path}` } + }), + toModelOutput, + }) +} diff --git a/apps/server/tests/tools/filesystem/bash.test.ts b/apps/server/tests/tools/filesystem/bash.test.ts new file mode 100644 index 00000000..d1ae84a2 --- /dev/null +++ b/apps/server/tests/tools/filesystem/bash.test.ts @@ -0,0 +1,98 @@ +import { afterEach, beforeEach, describe, expect, it } from 'bun:test' +import { mkdir, readFile, rm } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { createBashTool } from '../../../src/tools/filesystem/bash' +import type { FilesystemToolResult } from '../../../src/tools/filesystem/utils' + +let tmpDir: string +let exec: (params: Record) => Promise + +beforeEach(async () => { + tmpDir = join( + tmpdir(), + `fs-bash-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, + ) + await mkdir(tmpDir, { recursive: true }) + const tool = createBashTool(tmpDir) + exec = (params) => (tool as any).execute(params) +}) + +afterEach(async () => { + await rm(tmpDir, { recursive: true, force: true }) +}) + +describe('filesystem_bash', () => { + it('executes a simple command', async () => { + const result = await exec({ command: 'echo hello' }) + expect(result.isError).toBeUndefined() + expect(result.text.trim()).toBe('hello') + }) + + it('returns output from pwd', async () => { + const result = await exec({ command: 'pwd' }) + expect(result.isError).toBeUndefined() + expect(result.text.trim()).toContain(tmpDir) + }) + + it('captures stderr on failure', async () => { + const result = await exec({ command: 'ls /nonexistent_directory_xyz' }) + expect(result.isError).toBe(true) + expect(result.text).toContain('Exit code:') + }) + + it('returns exit code for failed commands', async () => { + const result = await exec({ command: 'exit 42' }) + expect(result.isError).toBe(true) + expect(result.text).toContain('[Exit code: 42]') + }) + + it('handles piped commands', async () => { + const result = await exec({ command: 'echo "a b c" | wc -w' }) + expect(result.isError).toBeUndefined() + expect(result.text.trim()).toBe('3') + }) + + it('times out long-running commands', async () => { + const result = await exec({ command: 'sleep 30', timeout: 1 }) + expect(result.isError).toBe(true) + expect(result.text).toContain('timed out') + }, 10_000) + + it('can create files', async () => { + await exec({ command: 'echo "created" > testfile.txt' }) + const content = await readFile(join(tmpDir, 'testfile.txt'), 'utf-8') + expect(content.trim()).toBe('created') + }) + + it('handles empty output commands', async () => { + const result = await exec({ command: 'true' }) + expect(result.isError).toBeUndefined() + expect(result.text).toBe('(no output)') + }) + + it('handles multiline output', async () => { + const result = await exec({ + command: 'echo "line1"; echo "line2"; echo "line3"', + }) + expect(result.text).toContain('line1') + expect(result.text).toContain('line2') + expect(result.text).toContain('line3') + }) + + it('uses cwd as working directory', async () => { + await mkdir(join(tmpDir, 'subdir')) + const subTool = createBashTool(join(tmpDir, 'subdir')) + const subExec = (params: Record) => + (subTool as any).execute(params) + + const result = await subExec({ command: 'pwd' }) + expect(result.text.trim()).toContain('subdir') + }) + + it('passes environment variables through', async () => { + const result = await exec({ command: 'echo $HOME' }) + expect(result.isError).toBeUndefined() + expect(result.text.trim().length).toBeGreaterThan(0) + }) +}) diff --git a/apps/server/tests/tools/filesystem/edit.test.ts b/apps/server/tests/tools/filesystem/edit.test.ts new file mode 100644 index 00000000..5c3e1c1f --- /dev/null +++ b/apps/server/tests/tools/filesystem/edit.test.ts @@ -0,0 +1,181 @@ +import { afterEach, beforeEach, describe, expect, it } from 'bun:test' +import { mkdir, readFile, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { createEditTool } from '../../../src/tools/filesystem/edit' +import type { FilesystemToolResult } from '../../../src/tools/filesystem/utils' + +let tmpDir: string +let exec: (params: Record) => Promise + +beforeEach(async () => { + tmpDir = join( + tmpdir(), + `fs-edit-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, + ) + await mkdir(tmpDir, { recursive: true }) + const tool = createEditTool(tmpDir) + exec = (params) => (tool as any).execute(params) +}) + +afterEach(async () => { + await rm(tmpDir, { recursive: true, force: true }) +}) + +describe('filesystem_edit', () => { + it('replaces an exact match', async () => { + await writeFile( + join(tmpDir, 'test.ts'), + 'const x = 1\nconst y = 2\nconst z = 3', + ) + const result = await exec({ + path: 'test.ts', + old_string: 'const y = 2', + new_string: 'const y = 42', + }) + expect(result.isError).toBeUndefined() + expect(result.text).toContain('Applied edit') + + const content = await readFile(join(tmpDir, 'test.ts'), 'utf-8') + expect(content).toBe('const x = 1\nconst y = 42\nconst z = 3') + }) + + it('errors when old_string not found', async () => { + await writeFile(join(tmpDir, 'test.ts'), 'const x = 1') + const result = await exec({ + path: 'test.ts', + old_string: 'nonexistent', + new_string: 'replacement', + }) + expect(result.isError).toBe(true) + expect(result.text).toContain('not found') + }) + + it('errors when multiple occurrences found', async () => { + await writeFile(join(tmpDir, 'test.ts'), 'foo\nbar\nfoo\nbaz') + const result = await exec({ + path: 'test.ts', + old_string: 'foo', + new_string: 'qux', + }) + expect(result.isError).toBe(true) + expect(result.text).toContain('2') + expect(result.text).toContain('occurrences') + }) + + it('errors when old_string equals new_string', async () => { + await writeFile(join(tmpDir, 'test.ts'), 'const x = 1') + const result = await exec({ + path: 'test.ts', + old_string: 'const x = 1', + new_string: 'const x = 1', + }) + expect(result.isError).toBe(true) + expect(result.text).toContain('identical') + }) + + it('errors for nonexistent file', async () => { + const result = await exec({ + path: 'missing.ts', + old_string: 'x', + new_string: 'y', + }) + expect(result.isError).toBe(true) + }) + + it('performs fuzzy match when whitespace differs', async () => { + await writeFile( + join(tmpDir, 'test.ts'), + ' const x = 1\n const y = 2\n const z = 3', + ) + const result = await exec({ + path: 'test.ts', + old_string: 'const y = 2', + new_string: ' const y = 42', + }) + expect(result.isError).toBeUndefined() + expect(result.text).toContain('Applied edit') + + const content = await readFile(join(tmpDir, 'test.ts'), 'utf-8') + expect(content).toContain('const y = 42') + }) + + it('preserves CRLF line endings', async () => { + await writeFile(join(tmpDir, 'crlf.ts'), 'line 1\r\nline 2\r\nline 3') + await exec({ + path: 'crlf.ts', + old_string: 'line 2', + new_string: 'modified line 2', + }) + + const content = await readFile(join(tmpDir, 'crlf.ts'), 'utf-8') + expect(content).toContain('\r\n') + expect(content).toContain('modified line 2') + }) + + it('preserves UTF-8 BOM', async () => { + await writeFile(join(tmpDir, 'bom.ts'), '\uFEFFconst x = 1') + await exec({ + path: 'bom.ts', + old_string: 'const x = 1', + new_string: 'const x = 2', + }) + + const content = await readFile(join(tmpDir, 'bom.ts'), 'utf-8') + expect(content.charCodeAt(0)).toBe(0xfeff) + expect(content).toContain('const x = 2') + }) + + it('generates a diff in the output', async () => { + await writeFile(join(tmpDir, 'test.ts'), 'hello world') + const result = await exec({ + path: 'test.ts', + old_string: 'hello world', + new_string: 'goodbye world', + }) + expect(result.text).toContain('- hello world') + expect(result.text).toContain('+ goodbye world') + }) + + it('handles multiline replacements', async () => { + await writeFile( + join(tmpDir, 'multi.ts'), + 'function foo() {\n return 1\n}\n\nfunction bar() {\n return 2\n}', + ) + const result = await exec({ + path: 'multi.ts', + old_string: 'function foo() {\n return 1\n}', + new_string: 'function foo() {\n return 42\n // updated\n}', + }) + expect(result.isError).toBeUndefined() + + const content = await readFile(join(tmpDir, 'multi.ts'), 'utf-8') + expect(content).toContain('return 42') + expect(content).toContain('// updated') + expect(content).toContain('function bar') + }) + + it('handles replacement that changes line count', async () => { + await writeFile(join(tmpDir, 'grow.ts'), 'a\nb\nc') + await exec({ + path: 'grow.ts', + old_string: 'b', + new_string: 'b1\nb2\nb3', + }) + + const content = await readFile(join(tmpDir, 'grow.ts'), 'utf-8') + expect(content).toBe('a\nb1\nb2\nb3\nc') + }) + + it('handles replacement that removes lines', async () => { + await writeFile(join(tmpDir, 'shrink.ts'), 'a\nb\nc\nd\ne') + await exec({ + path: 'shrink.ts', + old_string: 'b\nc\nd', + new_string: 'replaced', + }) + + const content = await readFile(join(tmpDir, 'shrink.ts'), 'utf-8') + expect(content).toBe('a\nreplaced\ne') + }) +}) diff --git a/apps/server/tests/tools/filesystem/find.test.ts b/apps/server/tests/tools/filesystem/find.test.ts new file mode 100644 index 00000000..78cc05fa --- /dev/null +++ b/apps/server/tests/tools/filesystem/find.test.ts @@ -0,0 +1,136 @@ +import { afterEach, beforeEach, describe, expect, it } from 'bun:test' +import { mkdir, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { createFindTool } from '../../../src/tools/filesystem/find' +import type { FilesystemToolResult } from '../../../src/tools/filesystem/utils' + +let tmpDir: string +let exec: (params: Record) => Promise + +beforeEach(async () => { + tmpDir = join( + tmpdir(), + `fs-find-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, + ) + await mkdir(tmpDir, { recursive: true }) + const tool = createFindTool(tmpDir) + exec = (params) => (tool as any).execute(params) +}) + +afterEach(async () => { + await rm(tmpDir, { recursive: true, force: true }) +}) + +async function createFileTree() { + await mkdir(join(tmpDir, 'src', 'components'), { recursive: true }) + await mkdir(join(tmpDir, 'tests'), { recursive: true }) + await mkdir(join(tmpDir, 'docs'), { recursive: true }) + await writeFile(join(tmpDir, 'src', 'index.ts'), '') + await writeFile(join(tmpDir, 'src', 'utils.ts'), '') + await writeFile(join(tmpDir, 'src', 'components', 'button.tsx'), '') + await writeFile(join(tmpDir, 'src', 'components', 'modal.tsx'), '') + await writeFile(join(tmpDir, 'tests', 'index.test.ts'), '') + await writeFile(join(tmpDir, 'docs', 'readme.md'), '') + await writeFile(join(tmpDir, 'package.json'), '{}') +} + +describe('filesystem_find', () => { + it('finds files matching a glob pattern', async () => { + await createFileTree() + const result = await exec({ pattern: '*.ts' }) + expect(result.isError).toBeUndefined() + expect(result.text).toContain('index.ts') + expect(result.text).toContain('utils.ts') + expect(result.text).toContain('index.test.ts') + }) + + it('finds tsx files', async () => { + await createFileTree() + const result = await exec({ pattern: '*.tsx' }) + expect(result.text).toContain('button.tsx') + expect(result.text).toContain('modal.tsx') + expect(result.text).not.toContain('.ts\n') + }) + + it('uses ** automatically for simple patterns', async () => { + await createFileTree() + const result = await exec({ pattern: '*.ts' }) + // Should find nested files too + expect(result.text).toContain('src/index.ts') + expect(result.text).toContain('tests/index.test.ts') + }) + + it('supports explicit recursive patterns', async () => { + await createFileTree() + const result = await exec({ pattern: 'src/**/*.ts' }) + expect(result.text).toContain('src/index.ts') + expect(result.text).toContain('src/utils.ts') + expect(result.text).not.toContain('tests/') + }) + + it('limits results', async () => { + await createFileTree() + const result = await exec({ pattern: '*', limit: 2 }) + const lines = result.text + .split('\n') + .filter((l) => l.trim() && !l.startsWith('(')) + expect(lines.length).toBe(2) + expect(result.text).toContain('limit=4') + }) + + it('returns no matches message', async () => { + await createFileTree() + const result = await exec({ pattern: '*.xyz' }) + expect(result.text).toContain('No files matching') + }) + + it('searches a subdirectory', async () => { + await createFileTree() + const result = await exec({ pattern: '*.tsx', path: 'src/components' }) + expect(result.text).toContain('button.tsx') + expect(result.text).toContain('modal.tsx') + }) + + it('skips node_modules', async () => { + await mkdir(join(tmpDir, 'node_modules', 'pkg'), { recursive: true }) + await writeFile(join(tmpDir, 'node_modules', 'pkg', 'index.js'), '') + await writeFile(join(tmpDir, 'src.js'), '') + const result = await exec({ pattern: '*.js' }) + expect(result.text).toContain('src.js') + expect(result.text).not.toContain('node_modules') + }) + + it('skips .git directory', async () => { + await mkdir(join(tmpDir, '.git', 'objects'), { recursive: true }) + await writeFile(join(tmpDir, '.git', 'config'), '') + await writeFile(join(tmpDir, 'real.txt'), '') + const result = await exec({ pattern: '*' }) + expect(result.text).toContain('real.txt') + expect(result.text).not.toContain('.git') + }) + + it('returns sorted results', async () => { + await createFileTree() + const result = await exec({ pattern: '*.ts' }) + const lines = result.text + .split('\n') + .filter((l) => l.trim() && !l.startsWith('(')) + const sorted = [...lines].sort() + expect(lines).toEqual(sorted) + }) + + it('finds dotfiles', async () => { + await writeFile(join(tmpDir, '.env'), 'SECRET=abc') + await writeFile(join(tmpDir, '.gitignore'), 'node_modules') + const result = await exec({ pattern: '.*' }) + expect(result.text).toContain('.env') + expect(result.text).toContain('.gitignore') + }) + + it('finds JSON files', async () => { + await createFileTree() + const result = await exec({ pattern: '*.json' }) + expect(result.text).toContain('package.json') + }) +}) diff --git a/apps/server/tests/tools/filesystem/grep.test.ts b/apps/server/tests/tools/filesystem/grep.test.ts new file mode 100644 index 00000000..4df132c6 --- /dev/null +++ b/apps/server/tests/tools/filesystem/grep.test.ts @@ -0,0 +1,154 @@ +import { afterEach, beforeEach, describe, expect, it } from 'bun:test' +import { mkdir, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { createGrepTool } from '../../../src/tools/filesystem/grep' +import type { FilesystemToolResult } from '../../../src/tools/filesystem/utils' + +let tmpDir: string +let exec: (params: Record) => Promise + +beforeEach(async () => { + tmpDir = join( + tmpdir(), + `fs-grep-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, + ) + await mkdir(tmpDir, { recursive: true }) + const tool = createGrepTool(tmpDir) + exec = (params) => (tool as any).execute(params) +}) + +afterEach(async () => { + await rm(tmpDir, { recursive: true, force: true }) +}) + +async function createTestFiles() { + await mkdir(join(tmpDir, 'src'), { recursive: true }) + await mkdir(join(tmpDir, 'lib'), { recursive: true }) + await writeFile( + join(tmpDir, 'src', 'main.ts'), + 'import { foo } from "./utils"\nconst bar = foo()\nconsole.log(bar)', + ) + await writeFile( + join(tmpDir, 'src', 'utils.ts'), + 'export function foo() {\n return 42\n}', + ) + await writeFile( + join(tmpDir, 'lib', 'helper.js'), + 'function helper() {\n return "help"\n}', + ) + await writeFile( + join(tmpDir, 'readme.md'), + '# Project\nThis is a project with foo and bar', + ) +} + +describe('filesystem_grep', () => { + it('finds matches across files', async () => { + await createTestFiles() + const result = await exec({ pattern: 'foo' }) + expect(result.isError).toBeUndefined() + expect(result.text).toContain('src/main.ts') + expect(result.text).toContain('src/utils.ts') + }) + + it('returns line numbers', async () => { + await createTestFiles() + const result = await exec({ pattern: 'foo' }) + expect(result.text).toMatch(/\d+/) + }) + + it('supports case-insensitive search', async () => { + await writeFile( + join(tmpDir, 'test.txt'), + 'Hello World\nhello world\nHELLO WORLD', + ) + const result = await exec({ pattern: 'hello', ignore_case: true }) + expect(result.text).toContain('Hello World') + expect(result.text).toContain('hello world') + expect(result.text).toContain('HELLO WORLD') + }) + + it('supports literal string search', async () => { + await writeFile(join(tmpDir, 'test.txt'), 'foo.bar()\nfooXbar()\nfoo bar') + const result = await exec({ pattern: 'foo.bar()', literal: true }) + expect(result.text).toContain('foo.bar()') + expect(result.text).not.toContain('fooXbar()') + }) + + it('supports glob filtering', async () => { + await createTestFiles() + const result = await exec({ pattern: 'function', glob: '*.ts' }) + expect(result.text).toContain('utils.ts') + expect(result.text).not.toContain('helper.js') + }) + + it('supports context lines', async () => { + await writeFile( + join(tmpDir, 'ctx.txt'), + 'line 1\nline 2\nmatch here\nline 4\nline 5', + ) + const result = await exec({ pattern: 'match here', context: 1 }) + expect(result.text).toContain('line 2') + expect(result.text).toContain('match here') + expect(result.text).toContain('line 4') + }) + + it('limits results', async () => { + await writeFile( + join(tmpDir, 'many.txt'), + Array.from({ length: 200 }, (_, i) => `match line ${i}`).join('\n'), + ) + const result = await exec({ pattern: 'match', limit: 5 }) + expect(result.text).toContain('limit=10') + }) + + it('returns no matches message', async () => { + await writeFile(join(tmpDir, 'test.txt'), 'hello world') + const result = await exec({ pattern: 'nonexistent_xyz' }) + expect(result.text).toContain('No matches') + }) + + it('handles invalid regex', async () => { + const result = await exec({ pattern: '[invalid(' }) + expect(result.isError).toBe(true) + expect(result.text).toContain('Invalid regex') + }) + + it('skips binary files', async () => { + await writeFile(join(tmpDir, 'data.png'), 'fake png with searchterm') + await writeFile(join(tmpDir, 'code.ts'), 'real code with searchterm') + const result = await exec({ pattern: 'searchterm' }) + expect(result.text).toContain('code.ts') + expect(result.text).not.toContain('data.png') + }) + + it('skips node_modules', async () => { + await mkdir(join(tmpDir, 'node_modules', 'pkg'), { recursive: true }) + await writeFile(join(tmpDir, 'node_modules', 'pkg', 'index.js'), 'findme') + await writeFile(join(tmpDir, 'src.ts'), 'findme') + const result = await exec({ pattern: 'findme' }) + expect(result.text).toContain('src.ts') + expect(result.text).not.toContain('node_modules') + }) + + it('searches a single file when path points to a file', async () => { + await writeFile(join(tmpDir, 'single.txt'), 'alpha\nbeta\ngamma') + const result = await exec({ pattern: 'beta', path: 'single.txt' }) + expect(result.text).toContain('beta') + expect(result.text).not.toContain('alpha') + }) + + it('handles regex special characters', async () => { + await writeFile(join(tmpDir, 'regex.txt'), 'price is $42.00\nno match') + const result = await exec({ pattern: '\\$\\d+\\.\\d+' }) + expect(result.text).toContain('$42.00') + }) + + it('truncates long matching lines', async () => { + const longLine = 'x'.repeat(1000) + await writeFile(join(tmpDir, 'long.txt'), longLine) + const result = await exec({ pattern: 'x' }) + expect(result.text).toContain('[truncated]') + }) +}) diff --git a/apps/server/tests/tools/filesystem/ls.test.ts b/apps/server/tests/tools/filesystem/ls.test.ts new file mode 100644 index 00000000..4cb81490 --- /dev/null +++ b/apps/server/tests/tools/filesystem/ls.test.ts @@ -0,0 +1,107 @@ +import { afterEach, beforeEach, describe, expect, it } from 'bun:test' +import { mkdir, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { createLsTool } from '../../../src/tools/filesystem/ls' +import type { FilesystemToolResult } from '../../../src/tools/filesystem/utils' + +let tmpDir: string +let exec: (params: Record) => Promise + +beforeEach(async () => { + tmpDir = join( + tmpdir(), + `fs-ls-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, + ) + await mkdir(tmpDir, { recursive: true }) + const tool = createLsTool(tmpDir) + exec = (params) => (tool as any).execute(params) +}) + +afterEach(async () => { + await rm(tmpDir, { recursive: true, force: true }) +}) + +describe('filesystem_ls', () => { + it('lists files and directories', async () => { + await mkdir(join(tmpDir, 'src')) + await writeFile(join(tmpDir, 'package.json'), '{}') + await writeFile(join(tmpDir, 'index.ts'), 'export {}') + + const result = await exec({}) + expect(result.isError).toBeUndefined() + expect(result.text).toContain('src/') + expect(result.text).toContain('package.json') + expect(result.text).toContain('index.ts') + }) + + it('shows directories first', async () => { + await mkdir(join(tmpDir, 'aaa-dir')) + await writeFile(join(tmpDir, 'bbb-file.txt'), 'x') + + const result = await exec({}) + const lines = result.text.split('\n') + const dirIdx = lines.findIndex((l) => l.includes('aaa-dir/')) + const fileIdx = lines.findIndex((l) => l.includes('bbb-file.txt')) + expect(dirIdx).toBeLessThan(fileIdx) + }) + + it('shows file sizes', async () => { + await writeFile(join(tmpDir, 'small.txt'), 'hello') + const result = await exec({}) + expect(result.text).toMatch(/small\.txt \(\d+B\)/) + }) + + it('handles empty directory', async () => { + const result = await exec({}) + expect(result.text).toBe('(empty directory)') + }) + + it('lists a subdirectory', async () => { + await mkdir(join(tmpDir, 'sub')) + await writeFile(join(tmpDir, 'sub', 'file.txt'), 'content') + const result = await exec({ path: 'sub' }) + expect(result.text).toContain('file.txt') + }) + + it('limits entries', async () => { + for (let i = 0; i < 10; i++) { + await writeFile(join(tmpDir, `file${i}.txt`), `content ${i}`) + } + const result = await exec({ limit: 3 }) + const lines = result.text + .split('\n') + .filter((l) => l.trim() && !l.startsWith('(')) + expect(lines.length).toBe(3) + expect(result.text).toContain('limit=6') + }) + + it('sorts entries alphabetically', async () => { + await writeFile(join(tmpDir, 'charlie.txt'), '') + await writeFile(join(tmpDir, 'alpha.txt'), '') + await writeFile(join(tmpDir, 'bravo.txt'), '') + + const result = await exec({}) + const lines = result.text.split('\n').filter(Boolean) + const names = lines.map((l) => l.split(' ')[0]) + expect(names).toEqual([...names].sort()) + }) + + it('errors for nonexistent directory', async () => { + const result = await exec({ path: 'nonexistent' }) + expect(result.isError).toBe(true) + }) + + it('handles large files size formatting', async () => { + const largeContent = 'x'.repeat(2 * 1024 * 1024) + await writeFile(join(tmpDir, 'large.bin'), largeContent) + const result = await exec({}) + expect(result.text).toContain('MB') + }) + + it('handles absolute path', async () => { + await writeFile(join(tmpDir, 'abs.txt'), 'data') + const result = await exec({ path: tmpDir }) + expect(result.text).toContain('abs.txt') + }) +}) diff --git a/apps/server/tests/tools/filesystem/read.test.ts b/apps/server/tests/tools/filesystem/read.test.ts new file mode 100644 index 00000000..9a6f0573 --- /dev/null +++ b/apps/server/tests/tools/filesystem/read.test.ts @@ -0,0 +1,132 @@ +import { afterEach, beforeEach, describe, expect, it } from 'bun:test' +import { mkdir, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { createReadTool } from '../../../src/tools/filesystem/read' +import type { FilesystemToolResult } from '../../../src/tools/filesystem/utils' + +let tmpDir: string +let exec: (params: Record) => Promise + +beforeEach(async () => { + tmpDir = join( + tmpdir(), + `fs-read-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, + ) + await mkdir(tmpDir, { recursive: true }) + const tool = createReadTool(tmpDir) + exec = (params) => (tool as any).execute(params) +}) + +afterEach(async () => { + await rm(tmpDir, { recursive: true, force: true }) +}) + +describe('filesystem_read', () => { + it('reads a text file with line numbers', async () => { + await writeFile(join(tmpDir, 'hello.txt'), 'line one\nline two\nline three') + const result = await exec({ path: 'hello.txt' }) + expect(result.isError).toBeUndefined() + expect(result.text).toContain('1 | line one') + expect(result.text).toContain('2 | line two') + expect(result.text).toContain('3 | line three') + }) + + it('reads with offset', async () => { + await writeFile(join(tmpDir, 'lines.txt'), 'a\nb\nc\nd\ne') + const result = await exec({ path: 'lines.txt', offset: 3 }) + expect(result.text).toContain('3 | c') + expect(result.text).toContain('4 | d') + expect(result.text).not.toContain('1 | a') + }) + + it('reads with limit', async () => { + await writeFile(join(tmpDir, 'lines.txt'), 'a\nb\nc\nd\ne') + const result = await exec({ path: 'lines.txt', limit: 2 }) + expect(result.text).toContain('1 | a') + expect(result.text).toContain('2 | b') + expect(result.text).not.toContain('3 | c') + }) + + it('reads with offset and limit', async () => { + await writeFile(join(tmpDir, 'lines.txt'), 'a\nb\nc\nd\ne') + const result = await exec({ path: 'lines.txt', offset: 2, limit: 2 }) + expect(result.text).toContain('2 | b') + expect(result.text).toContain('3 | c') + expect(result.text).not.toContain('1 | a') + expect(result.text).not.toContain('4 | d') + }) + + it('handles offset beyond end of file', async () => { + await writeFile(join(tmpDir, 'short.txt'), 'a\nb') + const result = await exec({ path: 'short.txt', offset: 100 }) + expect(result.text).toContain('2 lines') + expect(result.text).toContain('beyond end') + }) + + it('reads an empty file', async () => { + await writeFile(join(tmpDir, 'empty.txt'), '') + const result = await exec({ path: 'empty.txt' }) + expect(result.isError).toBeUndefined() + expect(result.text).toContain('1 | ') + }) + + it('reads an image file and returns base64', async () => { + const pngHeader = Buffer.from([ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, + ]) + await writeFile(join(tmpDir, 'image.png'), pngHeader) + const result = await exec({ path: 'image.png' }) + expect(result.images).toBeDefined() + expect(result.images?.length).toBe(1) + expect(result.images?.[0].mimeType).toBe('image/png') + expect(result.images?.[0].data).toBe(pngHeader.toString('base64')) + expect(result.text).toContain('Image:') + }) + + it('returns error for nonexistent file', async () => { + const result = await exec({ path: 'nonexistent.txt' }) + expect(result.isError).toBe(true) + }) + + it('resolves relative paths against cwd', async () => { + await mkdir(join(tmpDir, 'sub'), { recursive: true }) + await writeFile(join(tmpDir, 'sub', 'nested.txt'), 'nested content') + const result = await exec({ path: 'sub/nested.txt' }) + expect(result.text).toContain('nested content') + }) + + it('handles absolute paths', async () => { + const absPath = join(tmpDir, 'abs.txt') + await writeFile(absPath, 'absolute') + const result = await exec({ path: absPath }) + expect(result.text).toContain('absolute') + }) + + it('truncates large files', async () => { + const manyLines = Array.from( + { length: 5000 }, + (_, i) => `line ${i + 1}`, + ).join('\n') + await writeFile(join(tmpDir, 'large.txt'), manyLines) + const result = await exec({ path: 'large.txt' }) + expect(result.text).toContain('offset=') + expect(result.text).toContain('to continue reading') + }) + + it('handles files with UTF-8 BOM', async () => { + await writeFile(join(tmpDir, 'bom.txt'), '\uFEFFhello bom') + const result = await exec({ path: 'bom.txt' }) + expect(result.text).toContain('hello bom') + }) + + it('handles various image extensions', async () => { + const exts = ['.jpg', '.jpeg', '.gif', '.webp', '.svg'] + for (const ext of exts) { + await writeFile(join(tmpDir, `img${ext}`), 'fake image data') + const result = await exec({ path: `img${ext}` }) + expect(result.images).toBeDefined() + expect(result.images?.length).toBe(1) + } + }) +}) diff --git a/apps/server/tests/tools/filesystem/utils.test.ts b/apps/server/tests/tools/filesystem/utils.test.ts new file mode 100644 index 00000000..cebd39ab --- /dev/null +++ b/apps/server/tests/tools/filesystem/utils.test.ts @@ -0,0 +1,237 @@ +import { afterEach, beforeEach, describe, expect, it } from 'bun:test' +import { mkdir, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { + detectLineEnding, + isBinaryPath, + normalizeToLF, + restoreLineEndings, + stripBom, + truncateHead, + truncateLine, + truncateTail, + walkFiles, +} from '../../../src/tools/filesystem/utils' + +describe('truncateHead', () => { + it('does not truncate small content', () => { + const result = truncateHead('a\nb\nc') + expect(result.truncated).toBe(false) + expect(result.content).toBe('a\nb\nc') + expect(result.totalLines).toBe(3) + expect(result.keptLines).toBe(3) + }) + + it('truncates by line count', () => { + const content = Array.from({ length: 100 }, (_, i) => `line ${i}`).join( + '\n', + ) + const result = truncateHead(content, 10) + expect(result.truncated).toBe(true) + expect(result.keptLines).toBe(10) + expect(result.totalLines).toBe(100) + }) + + it('truncates by byte size', () => { + const content = Array.from({ length: 100 }, () => 'x'.repeat(200)).join( + '\n', + ) + const result = truncateHead(content, 10000, 1024) + expect(result.truncated).toBe(true) + expect(Buffer.byteLength(result.content, 'utf-8')).toBeLessThanOrEqual( + 1024 + 200, + ) + }) + + it('handles empty content', () => { + const result = truncateHead('') + expect(result.truncated).toBe(false) + expect(result.content).toBe('') + }) +}) + +describe('truncateTail', () => { + it('does not truncate small content', () => { + const result = truncateTail('a\nb\nc') + expect(result.truncated).toBe(false) + expect(result.content).toBe('a\nb\nc') + }) + + it('keeps last N lines', () => { + const lines = Array.from({ length: 100 }, (_, i) => `line ${i}`) + const content = lines.join('\n') + const result = truncateTail(content, 10) + expect(result.truncated).toBe(true) + expect(result.keptLines).toBe(10) + expect(result.content).toContain('line 99') + expect(result.content).not.toContain('line 0') + }) + + it('handles empty content', () => { + const result = truncateTail('') + expect(result.truncated).toBe(false) + expect(result.content).toBe('') + }) +}) + +describe('truncateLine', () => { + it('does not truncate short lines', () => { + expect(truncateLine('hello', 500)).toBe('hello') + }) + + it('truncates long lines', () => { + const long = 'x'.repeat(600) + const result = truncateLine(long, 500) + expect(result.length).toBe(500 + ' [truncated]'.length) + expect(result).toContain('[truncated]') + }) +}) + +describe('stripBom', () => { + it('strips BOM', () => { + const result = stripBom('\uFEFFhello') + expect(result.hasBom).toBe(true) + expect(result.content).toBe('hello') + }) + + it('handles content without BOM', () => { + const result = stripBom('hello') + expect(result.hasBom).toBe(false) + expect(result.content).toBe('hello') + }) +}) + +describe('detectLineEnding', () => { + it('detects CRLF', () => { + expect(detectLineEnding('a\r\nb')).toBe('\r\n') + }) + + it('detects CR', () => { + expect(detectLineEnding('a\rb')).toBe('\r') + }) + + it('defaults to LF', () => { + expect(detectLineEnding('a\nb')).toBe('\n') + expect(detectLineEnding('abc')).toBe('\n') + }) +}) + +describe('normalizeToLF', () => { + it('converts CRLF to LF', () => { + expect(normalizeToLF('a\r\nb')).toBe('a\nb') + }) + + it('converts CR to LF', () => { + expect(normalizeToLF('a\rb')).toBe('a\nb') + }) + + it('preserves LF', () => { + expect(normalizeToLF('a\nb')).toBe('a\nb') + }) +}) + +describe('restoreLineEndings', () => { + it('converts LF to CRLF', () => { + expect(restoreLineEndings('a\nb', '\r\n')).toBe('a\r\nb') + }) + + it('leaves LF as-is when target is LF', () => { + expect(restoreLineEndings('a\nb', '\n')).toBe('a\nb') + }) +}) + +describe('isBinaryPath', () => { + it('detects image files', () => { + expect(isBinaryPath('photo.png')).toBe(true) + expect(isBinaryPath('image.jpg')).toBe(true) + }) + + it('detects archives', () => { + expect(isBinaryPath('archive.zip')).toBe(true) + expect(isBinaryPath('package.tar.gz')).toBe(true) + }) + + it('returns false for text files', () => { + expect(isBinaryPath('code.ts')).toBe(false) + expect(isBinaryPath('readme.md')).toBe(false) + expect(isBinaryPath('data.json')).toBe(false) + }) + + it('returns false for extensionless files', () => { + expect(isBinaryPath('Makefile')).toBe(false) + }) +}) + +describe('walkFiles', () => { + let tmpDir: string + + beforeEach(async () => { + tmpDir = join( + tmpdir(), + `fs-walk-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, + ) + await mkdir(tmpDir, { recursive: true }) + }) + + afterEach(async () => { + await rm(tmpDir, { recursive: true, force: true }) + }) + + it('walks files recursively', async () => { + await mkdir(join(tmpDir, 'a', 'b'), { recursive: true }) + await writeFile(join(tmpDir, 'root.txt'), '') + await writeFile(join(tmpDir, 'a', 'mid.txt'), '') + await writeFile(join(tmpDir, 'a', 'b', 'deep.txt'), '') + + const files: string[] = [] + for await (const f of walkFiles(tmpDir, tmpDir)) { + files.push(f) + } + expect(files).toContain('root.txt') + expect(files).toContain(join('a', 'mid.txt')) + expect(files).toContain(join('a', 'b', 'deep.txt')) + }) + + it('skips node_modules', async () => { + await mkdir(join(tmpDir, 'node_modules', 'pkg'), { recursive: true }) + await writeFile(join(tmpDir, 'node_modules', 'pkg', 'index.js'), '') + await writeFile(join(tmpDir, 'real.ts'), '') + + const files: string[] = [] + for await (const f of walkFiles(tmpDir, tmpDir)) { + files.push(f) + } + expect(files).toContain('real.ts') + expect(files.some((f) => f.includes('node_modules'))).toBe(false) + }) + + it('skips .git', async () => { + await mkdir(join(tmpDir, '.git', 'objects'), { recursive: true }) + await writeFile(join(tmpDir, '.git', 'HEAD'), '') + await writeFile(join(tmpDir, 'code.ts'), '') + + const files: string[] = [] + for await (const f of walkFiles(tmpDir, tmpDir)) { + files.push(f) + } + expect(files).toContain('code.ts') + expect(files.some((f) => f.includes('.git'))).toBe(false) + }) + + it('handles empty directories', async () => { + const files: string[] = [] + for await (const f of walkFiles(tmpDir, tmpDir)) { + files.push(f) + } + expect(files.length).toBe(0) + }) + + it('handles nonexistent directory gracefully', async () => { + const files: string[] = [] + for await (const f of walkFiles(join(tmpDir, 'nonexistent'), tmpDir)) { + files.push(f) + } + expect(files.length).toBe(0) + }) +}) diff --git a/apps/server/tests/tools/filesystem/write.test.ts b/apps/server/tests/tools/filesystem/write.test.ts new file mode 100644 index 00000000..b419c75c --- /dev/null +++ b/apps/server/tests/tools/filesystem/write.test.ts @@ -0,0 +1,86 @@ +import { afterEach, beforeEach, describe, expect, it } from 'bun:test' +import { mkdir, readFile, rm, stat } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import type { FilesystemToolResult } from '../../../src/tools/filesystem/utils' +import { createWriteTool } from '../../../src/tools/filesystem/write' + +let tmpDir: string +let exec: (params: Record) => Promise + +beforeEach(async () => { + tmpDir = join( + tmpdir(), + `fs-write-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, + ) + await mkdir(tmpDir, { recursive: true }) + const tool = createWriteTool(tmpDir) + exec = (params) => (tool as any).execute(params) +}) + +afterEach(async () => { + await rm(tmpDir, { recursive: true, force: true }) +}) + +describe('filesystem_write', () => { + it('creates a new file', async () => { + const result = await exec({ path: 'new.txt', content: 'hello world' }) + expect(result.isError).toBeUndefined() + expect(result.text).toContain('Wrote') + expect(result.text).toContain('bytes') + + const content = await readFile(join(tmpDir, 'new.txt'), 'utf-8') + expect(content).toBe('hello world') + }) + + it('overwrites an existing file', async () => { + const filePath = join(tmpDir, 'exists.txt') + await Bun.write(filePath, 'old content') + + const result = await exec({ path: 'exists.txt', content: 'new content' }) + expect(result.isError).toBeUndefined() + + const content = await readFile(filePath, 'utf-8') + expect(content).toBe('new content') + }) + + it('creates parent directories automatically', async () => { + const result = await exec({ path: 'a/b/c/deep.txt', content: 'deep' }) + expect(result.isError).toBeUndefined() + + const content = await readFile(join(tmpDir, 'a/b/c/deep.txt'), 'utf-8') + expect(content).toBe('deep') + }) + + it('writes empty content', async () => { + const result = await exec({ path: 'empty.txt', content: '' }) + expect(result.isError).toBeUndefined() + + const info = await stat(join(tmpDir, 'empty.txt')) + expect(info.size).toBe(0) + }) + + it('reports byte count correctly for UTF-8', async () => { + const content = 'héllo wörld 🌍' + const result = await exec({ path: 'utf8.txt', content }) + const expectedBytes = Buffer.byteLength(content, 'utf-8') + expect(result.text).toContain(`${expectedBytes} bytes`) + }) + + it('writes multiline content', async () => { + const content = 'line 1\nline 2\nline 3' + await exec({ path: 'multi.txt', content }) + + const written = await readFile(join(tmpDir, 'multi.txt'), 'utf-8') + expect(written).toBe(content) + }) + + it('handles absolute paths', async () => { + const absPath = join(tmpDir, 'absolute.txt') + const result = await exec({ path: absPath, content: 'abs content' }) + expect(result.isError).toBeUndefined() + + const content = await readFile(absPath, 'utf-8') + expect(content).toBe('abs content') + }) +}) diff --git a/bun.lock b/bun.lock index abf5ba99..6cc4a04e 100644 --- a/bun.lock +++ b/bun.lock @@ -160,8 +160,6 @@ "@hono/mcp": "^0.2.3", "@hono/node-server": "^1.19.6", "@hono/zod-validator": "^0.4.3", - "@mariozechner/pi-agent-core": "^0.54.2", - "@mariozechner/pi-coding-agent": "^0.54.2", "@modelcontextprotocol/sdk": "^1.25.2", "@openrouter/ai-sdk-provider": "^2.2.3", "@sentry/bun": "^10.31.0", @@ -274,8 +272,6 @@ "@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="], - "@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.73.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-URURVzhxXGJDGUGFunIOtBlSl7KWvZiAAKY/ttTkZAkXT9bTPqdk2eK0b8qqSxXpikh3QKPnPYpiyX98zf5ebw=="], - "@apm-js-collab/code-transformer": ["@apm-js-collab/code-transformer@0.8.2", "", {}, "sha512-YRjJjNq5KFSjDUoqu5pFUWrrsvGOxl6c3bu+uMFc9HNNptZ2rNU/TI2nLw4jnhQNtka972Ee2m3uqbvDQtPeCA=="], "@apm-js-collab/tracing-hooks": ["@apm-js-collab/tracing-hooks@0.3.1", "", { "dependencies": { "@apm-js-collab/code-transformer": "^0.8.0", "debug": "^4.4.1", "module-details-from-path": "^1.0.4" } }, "sha512-Vu1CbmPURlN5fTboVuKMoJjbO5qcq9fA5YXpskx3dXe/zTBvjODFoerw+69rVBlRLrJpwPqSDqEuJDEKIrTldw=="], @@ -284,72 +280,10 @@ "@aws-crypto/crc32": ["@aws-crypto/crc32@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg=="], - "@aws-crypto/sha256-browser": ["@aws-crypto/sha256-browser@5.2.0", "", { "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-crypto/supports-web-crypto": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw=="], - - "@aws-crypto/sha256-js": ["@aws-crypto/sha256-js@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA=="], - - "@aws-crypto/supports-web-crypto": ["@aws-crypto/supports-web-crypto@5.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg=="], - "@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="], - "@aws-sdk/client-bedrock-runtime": ["@aws-sdk/client-bedrock-runtime@3.995.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.11", "@aws-sdk/credential-provider-node": "^3.972.10", "@aws-sdk/eventstream-handler-node": "^3.972.5", "@aws-sdk/middleware-eventstream": "^3.972.3", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", "@aws-sdk/middleware-user-agent": "^3.972.11", "@aws-sdk/middleware-websocket": "^3.972.6", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/token-providers": "3.995.0", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-endpoints": "3.995.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", "@aws-sdk/util-user-agent-node": "^3.972.10", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.23.2", "@smithy/eventstream-serde-browser": "^4.2.8", "@smithy/eventstream-serde-config-resolver": "^4.3.8", "@smithy/eventstream-serde-node": "^4.2.8", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.16", "@smithy/middleware-retry": "^4.4.33", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.10", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.32", "@smithy/util-defaults-mode-node": "^4.2.35", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-stream": "^4.5.12", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-nI7tT11L9s34AKr95GHmxs6k2+3ie+rEOew2cXOwsMC9k/5aifrZwh0JjAkBop4FqbmS8n0ZjCKDjBZFY/0YxQ=="], - - "@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.993.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.11", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", "@aws-sdk/middleware-user-agent": "^3.972.11", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-endpoints": "3.993.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", "@aws-sdk/util-user-agent-node": "^3.972.9", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.23.2", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.16", "@smithy/middleware-retry": "^4.4.33", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.10", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.32", "@smithy/util-defaults-mode-node": "^4.2.35", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-VLUN+wIeNX24fg12SCbzTUBnBENlL014yMKZvRhPkcn4wHR6LKgNrjsG3fZ03Xs0XoKaGtNFi1VVrq666sGBoQ=="], - - "@aws-sdk/core": ["@aws-sdk/core@3.973.11", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@aws-sdk/xml-builder": "^3.972.5", "@smithy/core": "^3.23.2", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-wdQ8vrvHkKIV7yNUKXyjPWKCdYEUrZTHJ8Ojd5uJxXp9vqPCkUR1dpi1NtOLcrDgueJH7MUH5lQZxshjFPSbDA=="], - - "@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.9", "", { "dependencies": { "@aws-sdk/core": "^3.973.11", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-ZptrOwQynfupubvcngLkbdIq/aXvl/czdpEG8XJ8mN8Nb19BR0jaK0bR+tfuMU36Ez9q4xv7GGkHFqEEP2hUUQ=="], - - "@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.11", "", { "dependencies": { "@aws-sdk/core": "^3.973.11", "@aws-sdk/types": "^3.973.1", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/node-http-handler": "^4.4.10", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "@smithy/util-stream": "^4.5.12", "tslib": "^2.6.2" } }, "sha512-hECWoOoH386bGr89NQc9vA/abkGf5TJrMREt+lhNcnSNmoBS04fK7vc3LrJBSQAUGGVj0Tz3f4dHB3w5veovig=="], - - "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.972.9", "", { "dependencies": { "@aws-sdk/core": "^3.973.11", "@aws-sdk/credential-provider-env": "^3.972.9", "@aws-sdk/credential-provider-http": "^3.972.11", "@aws-sdk/credential-provider-login": "^3.972.9", "@aws-sdk/credential-provider-process": "^3.972.9", "@aws-sdk/credential-provider-sso": "^3.972.9", "@aws-sdk/credential-provider-web-identity": "^3.972.9", "@aws-sdk/nested-clients": "3.993.0", "@aws-sdk/types": "^3.973.1", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-zr1csEu9n4eDiHMTYJabX1mDGuGLgjgUnNckIivvk43DocJC9/f6DefFrnUPZXE+GHtbW50YuXb+JIxKykU74A=="], - - "@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.9", "", { "dependencies": { "@aws-sdk/core": "^3.973.11", "@aws-sdk/nested-clients": "3.993.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-m4RIpVgZChv0vWS/HKChg1xLgZPpx8Z+ly9Fv7FwA8SOfuC6I3htcSaBz2Ch4bneRIiBUhwP4ziUo0UZgtJStQ=="], - - "@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.10", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.9", "@aws-sdk/credential-provider-http": "^3.972.11", "@aws-sdk/credential-provider-ini": "^3.972.9", "@aws-sdk/credential-provider-process": "^3.972.9", "@aws-sdk/credential-provider-sso": "^3.972.9", "@aws-sdk/credential-provider-web-identity": "^3.972.9", "@aws-sdk/types": "^3.973.1", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-70nCESlvnzjo4LjJ8By8MYIiBogkYPSXl3WmMZfH9RZcB/Nt9qVWbFpYj6Fk1vLa4Vk8qagFVeXgxdieMxG1QA=="], - - "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.9", "", { "dependencies": { "@aws-sdk/core": "^3.973.11", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-gOWl0Fe2gETj5Bk151+LYKpeGi2lBDLNu+NMNpHRlIrKHdBmVun8/AalwMK8ci4uRfG5a3/+zvZBMpuen1SZ0A=="], - - "@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.972.9", "", { "dependencies": { "@aws-sdk/client-sso": "3.993.0", "@aws-sdk/core": "^3.973.11", "@aws-sdk/token-providers": "3.993.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-ey7S686foGTArvFhi3ifQXmgptKYvLSGE2250BAQceMSXZddz7sUSNERGJT2S7u5KIe/kgugxrt01hntXVln6w=="], - - "@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.9", "", { "dependencies": { "@aws-sdk/core": "^3.973.11", "@aws-sdk/nested-clients": "3.993.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-8LnfS76nHXoEc9aRRiMMpxZxJeDG0yusdyo3NvPhCgESmBUgpMa4luhGbClW5NoX/qRcGxxM6Z/esqANSNMTow=="], - - "@aws-sdk/eventstream-handler-node": ["@aws-sdk/eventstream-handler-node@3.972.5", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/eventstream-codec": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-xEmd3dnyn83K6t4AJxBJA63wpEoCD45ERFG0XMTViD2E/Ohls9TLxjOWPb1PAxR9/46cKy/TImez1GoqP6xVNQ=="], - - "@aws-sdk/middleware-eventstream": ["@aws-sdk/middleware-eventstream@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-pbvZ6Ye/Ks6BAZPa3RhsNjHrvxU9li25PMhSdDpbX0jzdpKpAkIR65gXSNKmA/REnSdEMWSD4vKUW+5eMFzB6w=="], - - "@aws-sdk/middleware-host-header": ["@aws-sdk/middleware-host-header@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-aknPTb2M+G3s+0qLCx4Li/qGZH8IIYjugHMv15JTYMe6mgZO8VBpYgeGYsNMGCqCZOcWzuf900jFBG5bopfzmA=="], - - "@aws-sdk/middleware-logger": ["@aws-sdk/middleware-logger@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-Ftg09xNNRqaz9QNzlfdQWfpqMCJbsQdnZVJP55jfhbKi1+FTWxGuvfPoBhDHIovqWKjqbuiew3HuhxbJ0+OjgA=="], - - "@aws-sdk/middleware-recursion-detection": ["@aws-sdk/middleware-recursion-detection@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-PY57QhzNuXHnwbJgbWYTrqIDHYSeOlhfYERTAuc16LKZpTZRJUjzBFokp9hF7u1fuGeE3D70ERXzdbMBOqQz7Q=="], - - "@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.972.11", "", { "dependencies": { "@aws-sdk/core": "^3.973.11", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-endpoints": "3.993.0", "@smithy/core": "^3.23.2", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-R8CvPsPHXwzIHCAza+bllY6PrctEk4lYq/SkHJz9NLoBHCcKQrbOcsfXxO6xmipSbUNIbNIUhH0lBsJGgsRdiw=="], - - "@aws-sdk/middleware-websocket": ["@aws-sdk/middleware-websocket@3.972.6", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-format-url": "^3.972.3", "@smithy/eventstream-codec": "^4.2.8", "@smithy/eventstream-serde-browser": "^4.2.8", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-1DedO6N3m8zQ/vG6twNiHtsdwBgk773VdavLEbB3NXeKZDlzSK1BTviqWwvJdKx5UnIy4kGGP6WWpCEFEt/bhQ=="], - - "@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.995.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.11", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", "@aws-sdk/middleware-user-agent": "^3.972.11", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-endpoints": "3.995.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", "@aws-sdk/util-user-agent-node": "^3.972.10", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.23.2", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.16", "@smithy/middleware-retry": "^4.4.33", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.10", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.32", "@smithy/util-defaults-mode-node": "^4.2.35", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-7gq9gismVhESiRsSt0eYe1y1b6jS20LqLk+e/YSyPmGi9yHdndHQLIq73RbEJnK/QPpkQGFqq70M1mI46M1HGw=="], - - "@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/config-resolver": "^4.4.6", "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-v4J8qYAWfOMcZ4MJUyatntOicTzEMaU7j3OpkRCGGFSL2NgXQ5VbxauIyORA+pxdKZ0qQG2tCQjQjZDlXEC3Ow=="], - - "@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.995.0", "", { "dependencies": { "@aws-sdk/core": "^3.973.11", "@aws-sdk/nested-clients": "3.995.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-lYSadNdZZ513qCKoj/KlJ+PgCycL3n8ZNS37qLVFC0t7TbHzoxvGquu9aD2n9OCERAn43OMhQ7dXjYDYdjAXzA=="], - "@aws-sdk/types": ["@aws-sdk/types@3.972.0", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-U7xBIbLSetONxb2bNzHyDgND3oKGoIfmknrEVnoEU4GUSs+0augUOIn9DIWGUO2ETcRFdsRUnmx9KhPT9Ojbug=="], - "@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.995.0", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-endpoints": "^3.2.8", "tslib": "^2.6.2" } }, "sha512-aym/pjB8SLbo9w2nmkrDdAAVKVlf7CM71B9mKhjDbJTzwpSFBPHqJIMdDyj0mLumKC0aIVDr1H6U+59m9GvMFw=="], - - "@aws-sdk/util-format-url": ["@aws-sdk/util-format-url@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/querystring-builder": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-n7F2ycckcKFXa01vAsT/SJdjFHfKH9s96QHcs5gn8AaaigASICeME8WdUL9uBp8XV/OVwEt8+6gzn6KFUgQa8g=="], - - "@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.4", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-H1onv5SkgPBK2P6JR2MjGgbOnttoNzSPIRoeZTNPZYyaplwGg50zS3amXvXqF0/qfXpWEC9rLWU564QTB9bSog=="], - - "@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-JurOwkRUcXD/5MTDBcqdyQ9eVedtAsZgw5rBwktsPTN7QtPiS2Ld1jkJepNgYoCufz1Wcut9iup7GJDoIHp8Fw=="], - - "@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.972.10", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "^3.972.11", "@aws-sdk/types": "^3.973.1", "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-LVXzICPlsheET+sE6tkcS47Q5HkSTrANIlqL1iFxGAY/wRQ236DX/PCAK56qMh9QJoXAfXfoRW0B0Og4R+X7Nw=="], - - "@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.5", "", { "dependencies": { "@smithy/types": "^4.12.0", "fast-xml-parser": "5.3.6", "tslib": "^2.6.2" } }, "sha512-mCae5Ys6Qm1LDu0qdGwx2UQ63ONUe+FHw908fJzLDqFKTDBK4LDZUqKWm4OkTCNFq19bftjsBSESIGLD/s3/rA=="], - - "@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.3", "", {}, "sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw=="], - "@babel/code-frame": ["@babel/code-frame@7.28.6", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q=="], "@babel/compat-data": ["@babel/compat-data@7.28.6", "", {}, "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg=="], @@ -418,8 +352,6 @@ "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.14", "", { "os": "win32", "cpu": "x64" }, "sha512-oizCjdyQ3WJEswpb3Chdngeat56rIdSYK12JI3iI11Mt5T5EXcZ7WLuowzEaFPNJ3zmOQFliMN8QY1Pi+qsfdQ=="], - "@borewit/text-codec": ["@borewit/text-codec@0.2.1", "", {}, "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw=="], - "@braintree/sanitize-url": ["@braintree/sanitize-url@7.1.1", "", {}, "sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw=="], "@browseros-ai/agent-sdk": ["@browseros-ai/agent-sdk@workspace:packages/agent-sdk"], @@ -782,46 +714,12 @@ "@lydell/node-pty-win32-x64": ["@lydell/node-pty-win32-x64@1.1.0", "", { "os": "win32", "cpu": "x64" }, "sha512-3N56BZ+WDFnUMYRtsrr7Ky2mhWGl9xXcyqR6cexfuCqcz9RNWL+KoXRv/nZylY5dYaXkft4JaR1uVu+roiZDAw=="], - "@mariozechner/clipboard": ["@mariozechner/clipboard@0.3.2", "", { "optionalDependencies": { "@mariozechner/clipboard-darwin-arm64": "0.3.2", "@mariozechner/clipboard-darwin-universal": "0.3.2", "@mariozechner/clipboard-darwin-x64": "0.3.2", "@mariozechner/clipboard-linux-arm64-gnu": "0.3.2", "@mariozechner/clipboard-linux-arm64-musl": "0.3.2", "@mariozechner/clipboard-linux-riscv64-gnu": "0.3.2", "@mariozechner/clipboard-linux-x64-gnu": "0.3.2", "@mariozechner/clipboard-linux-x64-musl": "0.3.2", "@mariozechner/clipboard-win32-arm64-msvc": "0.3.2", "@mariozechner/clipboard-win32-x64-msvc": "0.3.2" } }, "sha512-IHQpksNjo7EAtGuHFU+tbWDp5LarH3HU/8WiB9O70ZEoBPHOg0/6afwSLK0QyNMMmx4Bpi/zl6+DcBXe95nWYA=="], - - "@mariozechner/clipboard-darwin-arm64": ["@mariozechner/clipboard-darwin-arm64@0.3.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-uBf6K7Je1ihsgvmWxA8UCGCeI+nbRVRXoarZdLjl6slz94Zs1tNKFZqx7aCI5O1i3e0B6ja82zZ06BWrl0MCVw=="], - - "@mariozechner/clipboard-darwin-universal": ["@mariozechner/clipboard-darwin-universal@0.3.2", "", { "os": "darwin" }, "sha512-mxSheKTW2U9LsBdXy0SdmdCAE5HqNS9QUmpNHLnfJ+SsbFKALjEZc5oRrVMXxGQSirDvYf5bjmRyT0QYYonnlg=="], - - "@mariozechner/clipboard-darwin-x64": ["@mariozechner/clipboard-darwin-x64@0.3.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-U1BcVEoidvwIp95+HJswSW+xr28EQiHR7rZjH6pn8Sja5yO4Yoe3yCN0Zm8Lo72BbSOK/fTSq0je7CJpaPCspg=="], - - "@mariozechner/clipboard-linux-arm64-gnu": ["@mariozechner/clipboard-linux-arm64-gnu@0.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-BsinwG3yWTIjdgNCxsFlip7LkfwPk+ruw/aFCXHUg/fb5XC/Ksp+YMQ7u0LUtiKzIv/7LMXgZInJQH6gxbAaqQ=="], - - "@mariozechner/clipboard-linux-arm64-musl": ["@mariozechner/clipboard-linux-arm64-musl@0.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-0/Gi5Xq2V6goXBop19ePoHvXsmJD9SzFlO3S+d6+T2b+BlPcpOu3Oa0wTjl+cZrLAAEzA86aPNBI+VVAFDFPKw=="], - - "@mariozechner/clipboard-linux-riscv64-gnu": ["@mariozechner/clipboard-linux-riscv64-gnu@0.3.2", "", { "os": "linux", "cpu": "none" }, "sha512-2AFFiXB24qf0zOZsxI1GJGb9wQGlOJyN6UwoXqmKS3dpQi/l6ix30IzDDA4c4ZcCcx4D+9HLYXhC1w7Sov8pXA=="], - - "@mariozechner/clipboard-linux-x64-gnu": ["@mariozechner/clipboard-linux-x64-gnu@0.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-v6fVnsn7WMGg73Dab8QMwyFce7tzGfgEixKgzLP8f1GJqkJZi5zO4k4FOHzSgUufgLil63gnxvMpjWkgfeQN7A=="], - - "@mariozechner/clipboard-linux-x64-musl": ["@mariozechner/clipboard-linux-x64-musl@0.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-xVUtnoMQ8v2JVyfJLKKXACA6avdnchdbBkTsZs8BgJQo29qwCp5NIHAUO8gbJ40iaEGToW5RlmVk2M9V0HsHEw=="], - - "@mariozechner/clipboard-win32-arm64-msvc": ["@mariozechner/clipboard-win32-arm64-msvc@0.3.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-AEgg95TNi8TGgak2wSXZkXKCvAUTjWoU1Pqb0ON7JHrX78p616XUFNTJohtIon3e0w6k0pYPZeCuqRCza/Tqeg=="], - - "@mariozechner/clipboard-win32-x64-msvc": ["@mariozechner/clipboard-win32-x64-msvc@0.3.2", "", { "os": "win32", "cpu": "x64" }, "sha512-tGRuYpZwDOD7HBrCpyRuhGnHHSCknELvqwKKUG4JSfSB7JIU7LKRh6zx6fMUOQd8uISK35TjFg5UcNih+vJhFA=="], - - "@mariozechner/jiti": ["@mariozechner/jiti@2.6.5", "", { "dependencies": { "std-env": "^3.10.0", "yoctocolors": "^2.1.2" }, "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-faGUlTcXka5l7rv0lP3K3vGW/ejRuOS24RR2aSFWREUQqzjgdsuWNo/IiPqL3kWRGt6Ahl2+qcDAwtdeWeuGUw=="], - - "@mariozechner/pi-agent-core": ["@mariozechner/pi-agent-core@0.54.2", "", { "dependencies": { "@mariozechner/pi-ai": "^0.54.2" } }, "sha512-dSg5tl3SGdrTFeTxfifvHjZ39M8k4jQ0ogTDtVeP7Pi3A3Whw4W1o6pYzTjX285CLxxqKiJS6MkwoElQHFwH1A=="], - - "@mariozechner/pi-ai": ["@mariozechner/pi-ai@0.54.2", "", { "dependencies": { "@anthropic-ai/sdk": "^0.73.0", "@aws-sdk/client-bedrock-runtime": "^3.983.0", "@google/genai": "^1.40.0", "@mistralai/mistralai": "1.10.0", "@sinclair/typebox": "^0.34.41", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "chalk": "^5.6.2", "openai": "6.10.0", "partial-json": "^0.1.7", "proxy-agent": "^6.5.0", "undici": "^7.19.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "pi-ai": "dist/cli.js" } }, "sha512-QKQV8iT7afwdaOiLDPTPyQcsGw4ulxBjAI0GvgvowAuqy9UbDeKFSdQYLmjVt7CtnJD1Z8zMjQQ4SLigdZ6dRQ=="], - - "@mariozechner/pi-coding-agent": ["@mariozechner/pi-coding-agent@0.54.2", "", { "dependencies": { "@mariozechner/jiti": "^2.6.2", "@mariozechner/pi-agent-core": "^0.54.2", "@mariozechner/pi-ai": "^0.54.2", "@mariozechner/pi-tui": "^0.54.2", "@silvia-odwyer/photon-node": "^0.3.4", "chalk": "^5.5.0", "cli-highlight": "^2.1.11", "diff": "^8.0.2", "file-type": "^21.1.1", "glob": "^13.0.1", "hosted-git-info": "^9.0.2", "ignore": "^7.0.5", "marked": "^15.0.12", "minimatch": "^10.1.1", "proper-lockfile": "^4.1.2", "yaml": "^2.8.2" }, "optionalDependencies": { "@mariozechner/clipboard": "^0.3.2" }, "bin": { "pi": "dist/cli.js" } }, "sha512-m4xozDZ7GdB9iXy8/ykaLZ7aCcINxOPhA9WYY+zd6Mb8DWoeo7YmXNBAfemACGlAAGsUW2cSKI66tboczA2Uag=="], - - "@mariozechner/pi-tui": ["@mariozechner/pi-tui@0.54.2", "", { "dependencies": { "@types/mime-types": "^2.1.4", "chalk": "^5.5.0", "get-east-asian-width": "^1.3.0", "koffi": "^2.9.0", "marked": "^15.0.12", "mime-types": "^3.0.1" } }, "sha512-ekk7x69qvESE7NMRO+VIduVV1T/kH+Ghroh8yqZ1y0IF4U85nzZ4jwV8JECuiGUvtFE0MMwWfJc9KdEur4xF6A=="], - "@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="], "@mdx-js/react": ["@mdx-js/react@3.1.1", "", { "dependencies": { "@types/mdx": "^2.0.0" }, "peerDependencies": { "@types/react": ">=16", "react": ">=16" } }, "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw=="], "@mermaid-js/parser": ["@mermaid-js/parser@0.6.3", "", { "dependencies": { "langium": "3.3.1" } }, "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA=="], - "@mistralai/mistralai": ["@mistralai/mistralai@1.10.0", "", { "dependencies": { "zod": "^3.20.0", "zod-to-json-schema": "^3.24.1" } }, "sha512-tdIgWs4Le8vpvPiUEWne6tK0qbVc+jMenujnvTqOjogrJUsCSQhus0tHTU1avDDh5//Rq2dFgP9mWRAdIEoBqg=="], - "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.25.3", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "jose": "^6.1.1", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.0" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-vsAMBMERybvYgKbg/l4L1rhS7VXV1c0CtyJg72vwxONVX0l4ZfKVAnZEWTQixJGTzKnELjQ59e4NbdFDALRiAQ=="], "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="], @@ -1340,10 +1238,6 @@ "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], - "@silvia-odwyer/photon-node": ["@silvia-odwyer/photon-node@0.3.4", "", {}, "sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA=="], - - "@sinclair/typebox": ["@sinclair/typebox@0.34.48", "", {}, "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA=="], - "@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="], "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@2.3.0", "", {}, "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg=="], @@ -1354,96 +1248,18 @@ "@sinonjs/samsam": ["@sinonjs/samsam@8.0.3", "", { "dependencies": { "@sinonjs/commons": "^3.0.1", "type-detect": "^4.1.0" } }, "sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ=="], - "@smithy/abort-controller": ["@smithy/abort-controller@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw=="], - - "@smithy/config-resolver": ["@smithy/config-resolver@4.4.6", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ=="], - - "@smithy/core": ["@smithy/core@3.23.3", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.9", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-stream": "^4.5.13", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-5IETfbqrTuGs0fC22ZnTW6df+PHlrWpSbAbySzTozsUROWPiOXDIWt1Y4dCDzhJUQ6H3ig/dFOZaEeLsTjNGRQ=="], - - "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.8", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw=="], - "@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.8", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.12.0", "@smithy/util-hex-encoding": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-jS/O5Q14UsufqoGhov7dHLOPCzkYJl9QDzusI2Psh4wyYx/izhzvX9P4D69aTxcdfVhEPhjK+wYyn/PzLjKbbw=="], - "@smithy/eventstream-serde-browser": ["@smithy/eventstream-serde-browser@4.2.8", "", { "dependencies": { "@smithy/eventstream-serde-universal": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-MTfQT/CRQz5g24ayXdjg53V0mhucZth4PESoA5IhvaWVDTOQLfo8qI9vzqHcPsdd2v6sqfTYqF5L/l+pea5Uyw=="], - - "@smithy/eventstream-serde-config-resolver": ["@smithy/eventstream-serde-config-resolver@4.3.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-ah12+luBiDGzBruhu3efNy1IlbwSEdNiw8fOZksoKoWW1ZHvO/04MQsdnws/9Aj+5b0YXSSN2JXKy/ClIsW8MQ=="], - - "@smithy/eventstream-serde-node": ["@smithy/eventstream-serde-node@4.2.8", "", { "dependencies": { "@smithy/eventstream-serde-universal": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-cYpCpp29z6EJHa5T9WL0KAlq3SOKUQkcgSoeRfRVwjGgSFl7Uh32eYGt7IDYCX20skiEdRffyDpvF2efEZPC0A=="], - - "@smithy/eventstream-serde-universal": ["@smithy/eventstream-serde-universal@4.2.8", "", { "dependencies": { "@smithy/eventstream-codec": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-iJ6YNJd0bntJYnX6s52NC4WFYcZeKrPUr1Kmmr5AwZcwCSzVpS7oavAmxMR7pMq7V+D1G4s9F5NJK0xwOsKAlQ=="], - - "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.9", "", { "dependencies": { "@smithy/protocol-http": "^5.3.8", "@smithy/querystring-builder": "^4.2.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA=="], - - "@smithy/hash-node": ["@smithy/hash-node@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA=="], - - "@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ=="], - "@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], - "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.8", "", { "dependencies": { "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A=="], - - "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.4.17", "", { "dependencies": { "@smithy/core": "^3.23.3", "@smithy/middleware-serde": "^4.2.9", "@smithy/node-config-provider": "^4.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-middleware": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-QP8wuZ7iSNEQ4/HyihTHlDUlQ3eBrCo+HoMm8l2gPcNrR4TA1RCC10jR7IyCnn3ASTrUwEnRaQ062vFC2/eYJw=="], - - "@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.34", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/service-error-classification": "^4.2.8", "@smithy/smithy-client": "^4.11.6", "@smithy/types": "^4.12.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-ROmCX/ev7ryOzgsQ6dnJ46gbVSrvR2HX7ioxkfXlrgfKEMMOUCWgl/OMOi7PZn95CXTxMMNJTbP3nkvWGFTz+w=="], - - "@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.9", "", { "dependencies": { "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ=="], - - "@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA=="], - - "@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.8", "", { "dependencies": { "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg=="], - - "@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.10", "", { "dependencies": { "@smithy/abort-controller": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/querystring-builder": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-u4YeUwOWRZaHbWaebvrs3UhwQwj+2VNmcVCwXcYTvPIuVyM7Ex1ftAj+fdbG/P4AkBwLq/+SKn+ydOI4ZJE9PA=="], - - "@smithy/property-provider": ["@smithy/property-provider@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w=="], - - "@smithy/protocol-http": ["@smithy/protocol-http@5.3.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ=="], - - "@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw=="], - - "@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA=="], - - "@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0" } }, "sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ=="], - - "@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.3", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg=="], - - "@smithy/signature-v4": ["@smithy/signature-v4@5.3.8", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg=="], - - "@smithy/smithy-client": ["@smithy/smithy-client@4.11.6", "", { "dependencies": { "@smithy/core": "^3.23.3", "@smithy/middleware-endpoint": "^4.4.17", "@smithy/middleware-stack": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-stream": "^4.5.13", "tslib": "^2.6.2" } }, "sha512-g9FNlCTfQzkSpHW3ILOm+TWZfXuOj2UcrNWNBHLnY3Ch+67mLVmiu3fGWPWbs1XiRK174q5tGphnPCTHvImQUA=="], - "@smithy/types": ["@smithy/types@4.12.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw=="], - "@smithy/url-parser": ["@smithy/url-parser@4.2.8", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA=="], - - "@smithy/util-base64": ["@smithy/util-base64@4.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ=="], - - "@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg=="], - - "@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.2.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA=="], - "@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], - "@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q=="], - - "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.33", "", { "dependencies": { "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.11.6", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-VutP/lyBWaTNUzNjI+NC3Kwts4Grhb8CTUyGZNQadf5lujqNy2IIM739D31qplSdbxqYBLOPvMXwy4CIKOArrg=="], - - "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.36", "", { "dependencies": { "@smithy/config-resolver": "^4.4.6", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.11.6", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-x73FjvOgG8XBtxu4auMnMDhLi6bUVBLHgNAv8xU0noDGks0KF59JNSzgVQ0oOSuf/D6pVJ5tMEkajwz6IavBUg=="], - - "@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.8", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw=="], - "@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], - "@smithy/util-middleware": ["@smithy/util-middleware@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A=="], - - "@smithy/util-retry": ["@smithy/util-retry@4.2.8", "", { "dependencies": { "@smithy/service-error-classification": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg=="], - - "@smithy/util-stream": ["@smithy/util-stream@4.5.13", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.9", "@smithy/node-http-handler": "^4.4.10", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-ZJQh++mmjO7JiWAW4SdWFrsde1VE038g4uGtkTlvCGcpytMLsxIAg9o9blorLYaQG47EfY9QjLP38od88NLL8w=="], - - "@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], - "@smithy/util-utf8": ["@smithy/util-utf8@4.2.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw=="], - "@smithy/uuid": ["@smithy/uuid@1.1.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw=="], - "@splinetool/runtime": ["@splinetool/runtime@0.9.526", "", { "dependencies": { "on-change": "^4.0.0", "semver-compare": "^1.0.0" } }, "sha512-qznHbXA5aKwDbCgESAothCNm1IeEZcmNWG145p5aXj4w5uoqR1TZ9qkTHTKLTsUbHeitCwdhzmRqan1kxboLgQ=="], "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], @@ -1496,10 +1312,6 @@ "@theguild/federation-composition": ["@theguild/federation-composition@0.21.3", "", { "dependencies": { "constant-case": "^3.0.4", "debug": "4.4.3", "json5": "^2.2.3", "lodash.sortby": "^4.7.0" }, "peerDependencies": { "graphql": "^16.0.0" } }, "sha512-+LlHTa4UbRpZBog3ggAxjYIFvdfH3UMvvBUptur19TMWkqU4+n3GmN+mDjejU+dyBXIG27c25RsiQP1HyvM99g=="], - "@tokenizer/inflate": ["@tokenizer/inflate@0.4.1", "", { "dependencies": { "debug": "^4.4.3", "token-types": "^6.1.1" } }, "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA=="], - - "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], - "@tokenlens/core": ["@tokenlens/core@1.3.0", "", {}, "sha512-d8YNHNC+q10bVpi95fELJwJyPVf1HfvBEI18eFQxRSZTdByXrP+f/ZtlhSzkx0Jl0aEmYVeBA5tPeeYRioLViQ=="], "@tokenlens/fetch": ["@tokenlens/fetch@1.3.0", "", { "dependencies": { "@tokenlens/core": "1.3.0" } }, "sha512-RONDRmETYly9xO8XMKblmrZjKSwCva4s5ebJwQNfNlChZoA5kplPoCgnWceHnn1J1iRjLVlrCNB43ichfmGBKQ=="], @@ -1638,8 +1450,6 @@ "@types/mdx": ["@types/mdx@2.0.13", "", {}, "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw=="], - "@types/mime-types": ["@types/mime-types@2.1.4", "", {}, "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w=="], - "@types/minimatch": ["@types/minimatch@5.1.2", "", {}, "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA=="], "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], @@ -1662,8 +1472,6 @@ "@types/request": ["@types/request@2.48.13", "", { "dependencies": { "@types/caseless": "*", "@types/node": "*", "@types/tough-cookie": "*", "form-data": "^2.5.5" } }, "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg=="], - "@types/retry": ["@types/retry@0.12.0", "", {}, "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA=="], - "@types/sinon": ["@types/sinon@21.0.0", "", { "dependencies": { "@types/sinonjs__fake-timers": "*" } }, "sha512-+oHKZ0lTI+WVLxx1IbJDNmReQaIsQJjN2e7UUrJHEeByG7bFeKJYsv1E75JxTQ9QKJDp21bAa/0W2Xo4srsDnw=="], "@types/sinonjs__fake-timers": ["@types/sinonjs__fake-timers@15.0.1", "", {}, "sha512-Ko2tjWJq8oozHzHV+reuvS5KYIRAokHnGbDwGh/J64LntgpbuylF74ipEL24HCyRjf9FOlBiBHWBR1RlVKsI1w=="], @@ -1796,8 +1604,6 @@ "antd-style": ["antd-style@3.7.1", "", { "dependencies": { "@ant-design/cssinjs": "^1.21.1", "@babel/runtime": "^7.24.1", "@emotion/cache": "^11.11.0", "@emotion/css": "^11.11.2", "@emotion/react": "^11.11.4", "@emotion/serialize": "^1.1.3", "@emotion/utils": "^1.2.1", "use-merge-value": "^1.2.0" }, "peerDependencies": { "antd": ">=5.8.1", "react": ">=18" } }, "sha512-CQOfddVp4aOvBfCepa+Kj2e7ap+2XBINg1Kn2osdE3oQvrD7KJu/K0sfnLcFLkgCJygbxmuazYdWLKb+drPDYA=="], - "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], - "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], @@ -1876,8 +1682,6 @@ "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], - "bowser": ["bowser@2.14.1", "", {}, "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg=="], - "boxen": ["boxen@8.0.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="], "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], @@ -1958,7 +1762,7 @@ "chrome-devtools-frontend": ["chrome-devtools-frontend@1.0.1577886", "", {}, "sha512-B9hY3o/0RuVCDWNYh9YnkEbRrPUMCY+NaOgBxvZRzGvqbGSMNckkVSdO67SwWR8bm4fo/qplXbUj0cSr229V6w=="], - "chrome-devtools-mcp": ["chrome-devtools-mcp@0.17.3", "", { "bin": { "chrome-devtools-mcp": "build/src/index.js" } }, "sha512-TcJIkvr5GXaVPAbsB0bpSVa0YiM694TvkdAN2TTKO94PXnZga2/2nmgIAVDm41QjJexhMCR+vO7J1rF8LwmiiQ=="], + "chrome-devtools-mcp": ["chrome-devtools-mcp@0.18.1", "", { "bin": { "chrome-devtools-mcp": "build/src/index.js" } }, "sha512-foYSH4oXtMCteFaKOggpcwYcU1R3RYvU1Bq8qNIOWjpP4GyroNn8mLKSYo+u1kcuujmoJ80sgBBIibRo68w3aQ=="], "chrome-launcher": ["chrome-launcher@1.2.0", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^2.0.1" }, "bin": { "print-chrome-path": "bin/print-chrome-path.cjs" } }, "sha512-JbuGuBNss258bvGil7FT4HKdC3SC2K7UAEUqiPy3ACS3Yxo3hAW6bvFpCu2HsIJLgTqxgEX6BkujvzZfLpUD0Q=="], @@ -1982,8 +1786,6 @@ "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], - "cli-highlight": ["cli-highlight@2.1.11", "", { "dependencies": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", "mz": "^2.4.0", "parse5": "^5.1.1", "parse5-htmlparser2-tree-adapter": "^6.0.0", "yargs": "^16.0.0" }, "bin": { "highlight": "bin/highlight" } }, "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg=="], - "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], "cli-truncate": ["cli-truncate@5.1.1", "", { "dependencies": { "slice-ansi": "^7.1.0", "string-width": "^8.0.0" } }, "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A=="], @@ -2370,8 +2172,6 @@ "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], - "fast-xml-parser": ["fast-xml-parser@5.3.6", "", { "dependencies": { "strnum": "^2.1.2" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-QNI3sAvSvaOiaMl8FYU4trnEzCwiRr8XMWgAHzlrWpTSj+QaCSvOf1h82OEP1s4hiAXhnbXSyFWCf4ldZzZRVA=="], - "fastest-levenshtein": ["fastest-levenshtein@1.0.16", "", {}, "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg=="], "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], @@ -2394,8 +2194,6 @@ "file-selector": ["file-selector@0.5.0", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-s8KNnmIDTBoD0p9uJ9uD0XY38SCeBOtj0UMXyQSLg1Ypfrfj8+dAvwsLjYQkQ2GjhVtp2HrnF5cJzMhBjfD8HA=="], - "file-type": ["file-type@21.3.0", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.4.0" } }, "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA=="], - "filesize": ["filesize@11.0.13", "", {}, "sha512-mYJ/qXKvREuO0uH8LTQJ6v7GsUvVOguqxg2VTwQUkyTPXXRRWPdjuUPVqdBrJQhvci48OHlNGRnux+Slr2Rnvw=="], "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], @@ -2564,8 +2362,6 @@ "help-me": ["help-me@5.0.0", "", {}, "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg=="], - "highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], - "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="], "hono": ["hono@4.11.4", "", {}, "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA=="], @@ -2574,7 +2370,7 @@ "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], - "hosted-git-info": ["hosted-git-info@9.0.2", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg=="], + "hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="], "html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="], @@ -2748,8 +2544,6 @@ "json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="], - "json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="], - "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], "json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="], @@ -2780,8 +2574,6 @@ "kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], - "koffi": ["koffi@2.15.1", "", {}, "sha512-mnc0C0crx/xMSljb5s9QbnLrlFHprioFO1hkXyuSuO/QtbpLDa0l/uM21944UfQunMKmp3/r789DTDxVyyH6aA=="], - "ky": ["ky@1.14.2", "", {}, "sha512-q3RBbsO5A5zrPhB6CaCS8ZUv+NWCXv6JJT4Em0i264G9W0fdPB8YRfnnEi7Dm7X7omAkBIPojzYJ2D1oHTHqug=="], "kysely": ["kysely@0.28.10", "", {}, "sha512-ksNxfzIW77OcZ+QWSAPC7yDqUSaIVwkTWnTPNiIy//vifNbwsSgQ57OkkncHxxpcBHM3LRfLAZVEh7kjq5twVA=="], @@ -3092,8 +2884,6 @@ "mute-stream": ["mute-stream@2.0.0", "", {}, "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA=="], - "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], - "nano-spawn": ["nano-spawn@1.0.3", "", {}, "sha512-jtpsQDetTnvS2Ts1fiRdci5rx0VYws5jGyC+4IYOTnIQ/wwdf6JdomlHBwqC3bJYOvaKu0C2GSZ1A60anrYpaA=="], "nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="], @@ -3176,8 +2966,6 @@ "open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], - "openai": ["openai@6.10.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-ITxOGo7rO3XRMiKA5l7tQ43iNNu+iXGFAcf2t+aWVzzqRaS0i7m1K2BhxNdaveB+5eENhO0VY1FkiZzhBk4v3A=="], - "ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="], "os-shim": ["os-shim@0.1.3", "", {}, "sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A=="], @@ -3194,8 +2982,6 @@ "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], - "p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="], - "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], "pac-proxy-agent": ["pac-proxy-agent@7.2.0", "", { "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.1.2", "debug": "^4.3.4", "get-uri": "^6.0.1", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.6", "pac-resolver": "^7.0.1", "socks-proxy-agent": "^8.0.5" } }, "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA=="], @@ -3222,16 +3008,12 @@ "parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="], - "parse5": ["parse5@5.1.1", "", {}, "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug=="], - - "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@6.0.1", "", { "dependencies": { "parse5": "^6.0.1" } }, "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA=="], + "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], "parseley": ["parseley@0.12.1", "", { "dependencies": { "leac": "^0.6.0", "peberminta": "^0.9.0" } }, "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw=="], "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], - "partial-json": ["partial-json@0.1.7", "", {}, "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA=="], - "pascal-case": ["pascal-case@3.1.2", "", { "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g=="], "path-case": ["path-case@3.0.4", "", { "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg=="], @@ -3328,8 +3110,6 @@ "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], - "proper-lockfile": ["proper-lockfile@4.1.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", "signal-exit": "^3.0.2" } }, "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA=="], - "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], "proto-list": ["proto-list@1.2.4", "", {}, "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA=="], @@ -3590,8 +3370,6 @@ "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], - "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], - "retry-request": ["retry-request@7.0.2", "", { "dependencies": { "@types/request": "^2.48.8", "extend": "^3.0.2", "teeny-request": "^9.0.0" } }, "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w=="], "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], @@ -3682,7 +3460,7 @@ "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], - "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], "signedsource": ["signedsource@1.0.0", "", {}, "sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww=="], @@ -3774,10 +3552,6 @@ "strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="], - "strnum": ["strnum@2.1.2", "", {}, "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ=="], - - "strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="], - "stubborn-fs": ["stubborn-fs@2.0.0", "", { "dependencies": { "stubborn-utils": "^1.0.1" } }, "sha512-Y0AvSwDw8y+nlSNFXMm2g6L51rBGdAQT20J3YSOqxC53Lo3bjWRtr2BKcfYoAf352WYpsZSTURrA0tqhfgudPA=="], "stubborn-utils": ["stubborn-utils@1.0.2", "", {}, "sha512-zOh9jPYI+xrNOyisSelgym4tolKTJCQd5GBhK0+0xJvcYDcwlOoxF/rnFKQ2KRZknXSG9jWAp66fwP6AxN9STg=="], @@ -3822,10 +3596,6 @@ "text-decoder": ["text-decoder@1.2.3", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA=="], - "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], - - "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], - "thread-stream": ["thread-stream@3.1.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A=="], "throttle-debounce": ["throttle-debounce@5.0.2", "", {}, "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A=="], @@ -3852,8 +3622,6 @@ "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], - "token-types": ["token-types@6.1.2", "", { "dependencies": { "@borewit/text-codec": "^0.2.1", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww=="], - "tokenlens": ["tokenlens@1.3.1", "", { "dependencies": { "@tokenlens/core": "1.3.0", "@tokenlens/fetch": "1.3.0", "@tokenlens/helpers": "1.3.1", "@tokenlens/models": "1.3.0" } }, "sha512-7oxmsS5PNCX3z+b+z07hL5vCzlgHKkCGrEQjQmWl5l+v5cUrtL7S1cuST4XThaL1XyjbTX8J5hfP0cjDJRkaLA=="], "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], @@ -3866,8 +3634,6 @@ "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], - "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], - "ts-dedent": ["ts-dedent@2.2.0", "", {}, "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="], "ts-import-resolver": ["ts-import-resolver@0.1.23", "", { "peerDependencies": { "typescript": ">=4.5.0" }, "optionalPeers": ["typescript"] }, "sha512-282pgr6j6aOvP3P2I6XugDxdBobkpdMmdbWjRjGl5gjPI1p0+oTNGDh1t924t75kRlyIkF65DiwhSIUysmyHQA=="], @@ -3906,8 +3672,6 @@ "uid": ["uid@2.0.2", "", { "dependencies": { "@lukeed/csprng": "^1.0.0" } }, "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g=="], - "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="], - "unc-path-regex": ["unc-path-regex@0.1.2", "", {}, "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg=="], "undici": ["undici@7.19.0", "", {}, "sha512-Heho1hJD81YChi+uS2RkSjcVO+EQLmLSyUlHyp7Y/wFbxQaGb4WXVKD073JytrjXJVkSZVzoE2MCSOKugFGtOQ=="], @@ -4104,76 +3868,8 @@ "@ant-design/cssinjs-utils/@ant-design/cssinjs": ["@ant-design/cssinjs@1.24.0", "", { "dependencies": { "@babel/runtime": "^7.11.1", "@emotion/hash": "^0.8.0", "@emotion/unitless": "^0.7.5", "classnames": "^2.3.1", "csstype": "^3.1.3", "rc-util": "^5.35.0", "stylis": "^4.3.4" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-K4cYrJBsgvL+IoozUXYjbT6LHHNt+19a9zkvpBPxLjFHas1UpPM2A5MlhROb0BT8N8WoavM5VsP9MeSeNK/3mg=="], - "@aws-crypto/sha256-browser/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-crypto/sha256-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], - - "@aws-crypto/sha256-js/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - "@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], - "@aws-sdk/client-bedrock-runtime/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/client-sso/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/client-sso/@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.993.0", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-endpoints": "^3.2.8", "tslib": "^2.6.2" } }, "sha512-j6vioBeRZ4eHX4SWGvGPpwGg/xSOcK7f1GL0VM+rdf3ZFTIsUEhCFmD78B+5r2PgztcECSzEfvHQX01k8dPQPw=="], - - "@aws-sdk/core/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/credential-provider-env/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/credential-provider-http/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/credential-provider-ini/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.993.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.11", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", "@aws-sdk/middleware-user-agent": "^3.972.11", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-endpoints": "3.993.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", "@aws-sdk/util-user-agent-node": "^3.972.9", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.23.2", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.16", "@smithy/middleware-retry": "^4.4.33", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.10", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.32", "@smithy/util-defaults-mode-node": "^4.2.35", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-iOq86f2H67924kQUIPOAvlmMaOAvOLoDOIb66I2YqSUpMYB6ufiuJW3RlREgskxv86S5qKzMnfy/X6CqMjK6XQ=="], - - "@aws-sdk/credential-provider-ini/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.993.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.11", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", "@aws-sdk/middleware-user-agent": "^3.972.11", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-endpoints": "3.993.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", "@aws-sdk/util-user-agent-node": "^3.972.9", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.23.2", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.16", "@smithy/middleware-retry": "^4.4.33", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.10", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.32", "@smithy/util-defaults-mode-node": "^4.2.35", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-iOq86f2H67924kQUIPOAvlmMaOAvOLoDOIb66I2YqSUpMYB6ufiuJW3RlREgskxv86S5qKzMnfy/X6CqMjK6XQ=="], - - "@aws-sdk/credential-provider-login/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/credential-provider-node/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/credential-provider-process/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/credential-provider-sso/@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.993.0", "", { "dependencies": { "@aws-sdk/core": "^3.973.11", "@aws-sdk/nested-clients": "3.993.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-+35g4c+8r7sB9Sjp1KPdM8qxGn6B/shBjJtEUN4e+Edw9UEQlZKIzioOGu3UAbyE0a/s450LdLZr4wbJChtmww=="], - - "@aws-sdk/credential-provider-sso/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/credential-provider-web-identity/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.993.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.11", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", "@aws-sdk/middleware-user-agent": "^3.972.11", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-endpoints": "3.993.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", "@aws-sdk/util-user-agent-node": "^3.972.9", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.23.2", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.16", "@smithy/middleware-retry": "^4.4.33", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.10", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.32", "@smithy/util-defaults-mode-node": "^4.2.35", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-iOq86f2H67924kQUIPOAvlmMaOAvOLoDOIb66I2YqSUpMYB6ufiuJW3RlREgskxv86S5qKzMnfy/X6CqMjK6XQ=="], - - "@aws-sdk/credential-provider-web-identity/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/eventstream-handler-node/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/middleware-eventstream/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/middleware-host-header/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/middleware-logger/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/middleware-recursion-detection/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/middleware-user-agent/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/middleware-user-agent/@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.993.0", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-endpoints": "^3.2.8", "tslib": "^2.6.2" } }, "sha512-j6vioBeRZ4eHX4SWGvGPpwGg/xSOcK7f1GL0VM+rdf3ZFTIsUEhCFmD78B+5r2PgztcECSzEfvHQX01k8dPQPw=="], - - "@aws-sdk/middleware-websocket/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/nested-clients/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/region-config-resolver/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/token-providers/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/util-endpoints/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/util-format-url/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/util-user-agent-browser/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - - "@aws-sdk/util-user-agent-node/@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="], - "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], @@ -4294,8 +3990,6 @@ "@graphql-tools/wrap/@graphql-tools/utils": ["@graphql-tools/utils@11.0.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA=="], - "@inquirer/core/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - "@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], @@ -4316,26 +4010,6 @@ "@lobehub/ui/url-join": ["url-join@5.0.0", "", {}, "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA=="], - "@mariozechner/pi-ai/@google/genai": ["@google/genai@1.42.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-+3nlMTcrQufbQ8IumGkOphxD5Pd5kKyJOzLcnY0/1IuE8upJk5aLmoexZ2BJhBp1zAjRJMEB4a2CJwKI9e2EYw=="], - - "@mariozechner/pi-ai/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], - - "@mariozechner/pi-ai/undici": ["undici@7.22.0", "", {}, "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg=="], - - "@mariozechner/pi-coding-agent/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], - - "@mariozechner/pi-coding-agent/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], - - "@mariozechner/pi-coding-agent/marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="], - - "@mariozechner/pi-coding-agent/minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], - - "@mariozechner/pi-tui/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], - - "@mariozechner/pi-tui/marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="], - - "@mariozechner/pi-tui/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], - "@modelcontextprotocol/sdk/zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], "@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], @@ -4630,8 +4304,6 @@ "chrome-launcher/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], - "cli-highlight/yargs": ["yargs@16.2.0", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="], - "cli-truncate/string-width": ["string-width@8.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.0", "strip-ansi": "^7.1.0" } }, "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg=="], "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -4674,8 +4346,6 @@ "execa/get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="], - "execa/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], "express/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], @@ -4688,8 +4358,6 @@ "find-up/path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], - "foreground-child/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - "fx-runner/commander": ["commander@2.9.0", "", { "dependencies": { "graceful-readlink": ">= 1.0.0" } }, "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A=="], "fx-runner/shell-quote": ["shell-quote@1.7.3", "", {}, "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw=="], @@ -4722,12 +4390,10 @@ "graphql-config/cosmiconfig": ["cosmiconfig@8.3.6", "", { "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0", "path-type": "^4.0.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA=="], - "hast-util-from-html/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], - - "hast-util-raw/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], - "hoist-non-react-statics/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], + "hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "html-to-text/htmlparser2": ["htmlparser2@8.0.2", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1", "entities": "^4.4.0" } }, "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA=="], "htmlparser2/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], @@ -4770,8 +4436,6 @@ "node-notifier/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], - "normalize-package-data/hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="], - "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], "nypm/citty": ["citty@0.2.0", "", {}, "sha512-8csy5IBFI2ex2hTVpaHN2j+LNE199AgiI7y4dMintrr8i0lQiFn+0AWMZrWdHKIgMOer65f8IThysYhoReqjWA=="], @@ -4784,15 +4448,13 @@ "ora/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], - "p-retry/retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], - "pac-proxy-agent/agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], "pac-proxy-agent/https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], - "parse5-htmlparser2-tree-adapter/parse5": ["parse5@6.0.1", "", {}, "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="], + "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], "pino/pino-abstract-transport": ["pino-abstract-transport@2.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw=="], @@ -4830,8 +4492,6 @@ "read-pkg/unicorn-magic": ["unicorn-magic@0.1.0", "", {}, "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ=="], - "restore-cursor/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - "schema-utils/ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="], "send/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], @@ -4908,18 +4568,8 @@ "@aklinker1/rollup-plugin-visualizer/open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], - "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], - "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], - "@aws-sdk/credential-provider-ini/@aws-sdk/nested-clients/@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.993.0", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-endpoints": "^3.2.8", "tslib": "^2.6.2" } }, "sha512-j6vioBeRZ4eHX4SWGvGPpwGg/xSOcK7f1GL0VM+rdf3ZFTIsUEhCFmD78B+5r2PgztcECSzEfvHQX01k8dPQPw=="], - - "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.993.0", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-endpoints": "^3.2.8", "tslib": "^2.6.2" } }, "sha512-j6vioBeRZ4eHX4SWGvGPpwGg/xSOcK7f1GL0VM+rdf3ZFTIsUEhCFmD78B+5r2PgztcECSzEfvHQX01k8dPQPw=="], - - "@aws-sdk/credential-provider-sso/@aws-sdk/token-providers/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.993.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.11", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", "@aws-sdk/middleware-user-agent": "^3.972.11", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-endpoints": "3.993.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", "@aws-sdk/util-user-agent-node": "^3.972.9", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.23.2", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.16", "@smithy/middleware-retry": "^4.4.33", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.10", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.32", "@smithy/util-defaults-mode-node": "^4.2.35", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-iOq86f2H67924kQUIPOAvlmMaOAvOLoDOIb66I2YqSUpMYB6ufiuJW3RlREgskxv86S5qKzMnfy/X6CqMjK6XQ=="], - - "@aws-sdk/credential-provider-web-identity/@aws-sdk/nested-clients/@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.993.0", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-endpoints": "^3.2.8", "tslib": "^2.6.2" } }, "sha512-j6vioBeRZ4eHX4SWGvGPpwGg/xSOcK7f1GL0VM+rdf3ZFTIsUEhCFmD78B+5r2PgztcECSzEfvHQX01k8dPQPw=="], - "@browseros/server/@types/bun/bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="], "@google/gemini-cli-core/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.203.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ=="], @@ -4960,16 +4610,6 @@ "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - "@mariozechner/pi-ai/@google/genai/google-auth-library": ["google-auth-library@10.5.0", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.0.0", "gcp-metadata": "^8.0.0", "google-logging-utils": "^1.0.0", "gtoken": "^8.0.0", "jws": "^4.0.0" } }, "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w=="], - - "@mariozechner/pi-coding-agent/glob/minimatch": ["minimatch@10.2.2", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw=="], - - "@mariozechner/pi-coding-agent/glob/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], - - "@mariozechner/pi-coding-agent/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], - - "@mariozechner/pi-tui/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], - "@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/otlp-transformer/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.203.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ=="], "@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/otlp-transformer/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], @@ -5142,10 +4782,6 @@ "boxen/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], - "cli-highlight/yargs/cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], - - "cli-highlight/yargs/yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], - "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "concat-stream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], @@ -5176,10 +4812,6 @@ "graphql-config/cosmiconfig/path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], - "hast-util-from-html/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], - - "hast-util-raw/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], - "jszip/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], "merge-value/set-value/is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], @@ -5188,8 +4820,6 @@ "multimatch/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], - "normalize-package-data/hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "ora/log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], "ora/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], @@ -5230,12 +4860,8 @@ "wxt/chokidar/readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], - "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], - "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], - "@aws-sdk/credential-provider-sso/@aws-sdk/token-providers/@aws-sdk/nested-clients/@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.993.0", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-endpoints": "^3.2.8", "tslib": "^2.6.2" } }, "sha512-j6vioBeRZ4eHX4SWGvGPpwGg/xSOcK7f1GL0VM+rdf3ZFTIsUEhCFmD78B+5r2PgztcECSzEfvHQX01k8dPQPw=="], - "@google/gemini-cli-core/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/otlp-transformer/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], "@google/gemini-cli-core/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/otlp-transformer/@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g=="], @@ -5254,20 +4880,8 @@ "@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "@mariozechner/pi-ai/@google/genai/google-auth-library/gaxios": ["gaxios@7.1.3", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2", "rimraf": "^5.0.1" } }, "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ=="], - - "@mariozechner/pi-ai/@google/genai/google-auth-library/gcp-metadata": ["gcp-metadata@8.1.2", "", { "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", "json-bigint": "^1.0.0" } }, "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg=="], - - "@mariozechner/pi-ai/@google/genai/google-auth-library/gtoken": ["gtoken@8.0.0", "", { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw=="], - - "@mariozechner/pi-coding-agent/glob/minimatch/brace-expansion": ["brace-expansion@5.0.3", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA=="], - "@sentry/bundler-plugin-core/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "cli-highlight/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "cli-highlight/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - "fx-runner/which/is-absolute/is-relative": ["is-relative@0.1.3", "", {}, "sha512-wBOr+rNM4gkAZqoLRJI4myw5WzzIdQosFAAbnvfXP5z1LyzgAI3ivOKehC5KfqlQJZoihVhirgtCBj378Eg8GA=="], "graphql-config/@graphql-tools/url-loader/@graphql-tools/executor-graphql-ws/@graphql-tools/executor-common": ["@graphql-tools/executor-common@0.0.6", "", { "dependencies": { "@envelop/core": "^5.3.0", "@graphql-tools/utils": "^10.9.1" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-JAH/R1zf77CSkpYATIJw+eOJwsbWocdDjY+avY7G+P5HCXxwQjAjWVkJI1QJBQYjPQDVxwf1fmTZlIN3VOadow=="], @@ -5292,16 +4906,6 @@ "@google/genai/google-auth-library/gaxios/rimraf/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], - "@mariozechner/pi-ai/@google/genai/google-auth-library/gaxios/https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], - - "@mariozechner/pi-ai/@google/genai/google-auth-library/gaxios/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], - - "@mariozechner/pi-ai/@google/genai/google-auth-library/gaxios/rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], - - "@mariozechner/pi-coding-agent/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - - "cli-highlight/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "graphql-config/@graphql-tools/url-loader/@graphql-tools/wrap/@graphql-tools/delegate/@graphql-tools/batch-execute": ["@graphql-tools/batch-execute@9.0.19", "", { "dependencies": { "@graphql-tools/utils": "^10.9.1", "@whatwg-node/promise-helpers": "^1.3.0", "dataloader": "^2.2.3", "tslib": "^2.8.1" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-VGamgY4PLzSx48IHPoblRw0oTaBa7S26RpZXt0Y4NN90ytoE0LutlpB2484RbkfcTjv9wa64QD474+YP1kEgGA=="], "pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], @@ -5314,14 +4918,6 @@ "@google/genai/google-auth-library/gaxios/rimraf/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - "@mariozechner/pi-ai/@google/genai/google-auth-library/gaxios/https-proxy-agent/agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], - - "@mariozechner/pi-ai/@google/genai/google-auth-library/gaxios/rimraf/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], - "@google/genai/google-auth-library/gaxios/rimraf/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - - "@mariozechner/pi-ai/@google/genai/google-auth-library/gaxios/rimraf/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - - "@mariozechner/pi-ai/@google/genai/google-auth-library/gaxios/rimraf/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], } } From 3a3ba57710501543a4e145e5dd55fe5cce5ad464 Mon Sep 17 00:00:00 2001 From: Nikhil Sonti Date: Thu, 26 Feb 2026 14:55:47 -0800 Subject: [PATCH 2/2] fix: add explicit ENOENT handling in grep tool stat() call Co-Authored-By: Claude Opus 4.6 --- apps/server/src/tools/filesystem/grep.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/server/src/tools/filesystem/grep.ts b/apps/server/src/tools/filesystem/grep.ts index 82860849..0f2cad64 100644 --- a/apps/server/src/tools/filesystem/grep.ts +++ b/apps/server/src/tools/filesystem/grep.ts @@ -146,8 +146,15 @@ export function createGrepTool(cwd: string) { globMatcher = new Bun.Glob(effectiveGlob) } - // Check if searching a single file - const pathStat = await stat(searchPath) + let pathStat: Awaited> + try { + pathStat = await stat(searchPath) + } catch { + return { + text: `Path not found: ${params.path || '.'}`, + isError: true, + } + } const allMatches: GrepMatch[] = [] let totalMatchCount = 0