From 5d80b682b22c2bb35a7d4f445ae965e5e66b86b1 Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Wed, 14 Jan 2026 18:12:50 -0600 Subject: [PATCH 01/14] initial implementatiton --- backend/bun.lock | 8 + backend/package.json | 2 + backend/src/db/entities/Message.ts | 1 - backend/src/db/entities/ToolCall.ts | 8 + backend/src/db/seed.ts | 6 + backend/src/providers/base.ts | 3 +- backend/src/providers/codee.ts | 2 +- backend/src/tools/dynamic.ts | 6 + backend/src/tools/kernel/index.ts | 576 +++++++++++++++++++++++ backend/src/workflows/agent.ts | 14 +- backend/src/workflows/helpers/agents.ts | 20 +- backend/src/workflows/helpers/sandbox.ts | 12 +- backend/src/workflows/steps.ts | 22 +- 13 files changed, 663 insertions(+), 17 deletions(-) create mode 100644 backend/src/tools/kernel/index.ts diff --git a/backend/bun.lock b/backend/bun.lock index 489935f..ea5f1ef 100644 --- a/backend/bun.lock +++ b/backend/bun.lock @@ -6,6 +6,8 @@ "name": "backend", "dependencies": { "@ai-sdk/openai": "^3.0.0", + "@onkernel/ai-sdk": "^0.0.3", + "@onkernel/sdk": "^0.25.0", "@posthog/agent-toolkit": "^0.2.4", "@posthog/ai": "^7.3.0", "@trpc/server": "^11.0.0-rc.553", @@ -328,6 +330,10 @@ "@oclif/plugin-help": ["@oclif/plugin-help@6.2.31", "", { "dependencies": { "@oclif/core": "^4" } }, "sha512-o4xR98DEFf+VqY+M9B3ZooTm2T/mlGvyBHwHcnsPJCEnvzHqEA9xUlCUK4jm7FBXHhkppziMgCC2snsueLoIpQ=="], + "@onkernel/ai-sdk": ["@onkernel/ai-sdk@0.0.3", "", { "dependencies": { "zod": "^4.1.12" }, "peerDependencies": { "@onkernel/sdk": "*", "ai": "^5" } }, "sha512-844KPxvyM6t5LJCZ5hX9FNrQfJRyLgVtEY2twtqTuL8/vPs7yqhu6gx+SbOV1R3sUYnNuI2gPL0FtiimqbRaNA=="], + + "@onkernel/sdk": ["@onkernel/sdk@0.25.0", "", {}, "sha512-kMZ/499V9KCksvI/IxYx8juBKViWaCBLsoCOaZdfvLuXBy15310V+yoNUqu+J5q4Yfh+rHBcpFxn9H+GHfHfOQ=="], + "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], "@oxc-minify/binding-android-arm64": ["@oxc-minify/binding-android-arm64@0.96.0", "", { "os": "android", "cpu": "arm64" }, "sha512-lzeIEMu/v6Y+La5JSesq4hvyKtKBq84cgQpKYTYM/yGuNk2tfd5Ha31hnC+mTh48lp/5vZH+WBfjVUjjINCfug=="], @@ -1848,6 +1854,8 @@ "@oclif/core/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + "@onkernel/ai-sdk/zod": ["zod@4.2.1", "", {}, "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw=="], + "@posthog/agent-toolkit/ai": ["ai@5.0.116", "", { "dependencies": { "@ai-sdk/gateway": "2.0.23", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-+2hYJ80/NcDWuv9K2/MLP3cTCFgwWHmHlS1tOpFUKKcmLbErAAlE/S2knsKboc3PNAu8pQkDr2N3K/Vle7ENgQ=="], "@posthog/ai/zod": ["zod@4.2.1", "", {}, "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw=="], diff --git a/backend/package.json b/backend/package.json index 5c08f94..459a7bb 100644 --- a/backend/package.json +++ b/backend/package.json @@ -27,6 +27,8 @@ }, "dependencies": { "@ai-sdk/openai": "^3.0.0", + "@onkernel/ai-sdk": "^0.0.3", + "@onkernel/sdk": "^0.25.0", "@posthog/agent-toolkit": "^0.2.4", "@posthog/ai": "^7.3.0", "@trpc/server": "^11.0.0-rc.553", diff --git a/backend/src/db/entities/Message.ts b/backend/src/db/entities/Message.ts index 6fed8cd..7a23cbe 100644 --- a/backend/src/db/entities/Message.ts +++ b/backend/src/db/entities/Message.ts @@ -47,7 +47,6 @@ export class Message { @Column({ type: 'int', default: 0 }) costMicrodollars!: number; - @Column({ type: 'int', default: 0 }) sandboxDurationMs!: number; diff --git a/backend/src/db/entities/ToolCall.ts b/backend/src/db/entities/ToolCall.ts index 3dbbfca..ef2dbea 100644 --- a/backend/src/db/entities/ToolCall.ts +++ b/backend/src/db/entities/ToolCall.ts @@ -2,6 +2,11 @@ import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, CreateDateColumn, In import type { Agent } from './Agent'; import type { Message } from './Message'; +export type ToolCallImage = { + data: string; + mimeType: string; +}; + @Entity() export class ToolCall { @PrimaryGeneratedColumn() @@ -26,6 +31,9 @@ export class ToolCall { @Column({ type: 'text', default: '' }) result!: string; + @Column({ type: 'jsonb', default: [] }) + images!: ToolCallImage[]; + @Column({ length: 20, default: 'success' }) status!: string; } diff --git a/backend/src/db/seed.ts b/backend/src/db/seed.ts index 0b0fb9b..dc4a1b5 100644 --- a/backend/src/db/seed.ts +++ b/backend/src/db/seed.ts @@ -39,6 +39,12 @@ const PROVIDER_SEEDS: ProviderSeed[] = [ }, ], }, + { + slug: 'kernel', + displayName: 'Kernel.sh', + hasCloudAgent: false, + tools: [{ displayName: 'Browser Automation', slugName: 'kernel/browser' }], + }, { slug: 'cursor', displayName: 'Cursor', diff --git a/backend/src/providers/base.ts b/backend/src/providers/base.ts index 6b98da6..91f2f95 100644 --- a/backend/src/providers/base.ts +++ b/backend/src/providers/base.ts @@ -1,6 +1,7 @@ import { Agent } from '../db/entities/Agent'; import { Workspace } from '../db/entities/Workspace'; import type { SenderType, MessageImage } from '../db/entities/Message'; +import type { ToolCallImage } from '../db/entities/ToolCall'; export type ProviderToolCall = { id: number; @@ -9,7 +10,7 @@ export type ProviderToolCall = { arguments: Record; result: string; status: string; - duration_ms: number | null; + images: ToolCallImage[]; }; export type ProviderMessage = { diff --git a/backend/src/providers/codee.ts b/backend/src/providers/codee.ts index 89255f4..869552a 100644 --- a/backend/src/providers/codee.ts +++ b/backend/src/providers/codee.ts @@ -103,7 +103,7 @@ export class CodeeProvider implements CloudProvider { arguments: toolCall.arguments, result: toolCall.result, status: toolCall.status, - duration_ms: toolCall.durationMs, + images: toolCall.images, }); toolCallsByMessage.set(toolCall.message.id, list); } diff --git a/backend/src/tools/dynamic.ts b/backend/src/tools/dynamic.ts index 087278f..397d8ad 100644 --- a/backend/src/tools/dynamic.ts +++ b/backend/src/tools/dynamic.ts @@ -1,6 +1,7 @@ import type { Sandbox } from '@vercel/sandbox'; import { buildQueryRunnerTools, buildInsightTools, buildErrorTools, buildDocumentationTools, type ToolCollection } from './posthog/index'; import { buildCommitTools } from './github/commits'; +import { buildBrowserTools } from './kernel/index'; export async function buildDynamicTools(agentId: number, toolSlugs: string[], sandbox: Sandbox): Promise { const tools: ToolCollection = {}; @@ -32,5 +33,10 @@ export async function buildDynamicTools(agentId: number, toolSlugs: string[], sa Object.assign(tools, buildCommitTools(sandbox)); } + if (toolSlugs.includes('kernel/browser')) { + const browserTools = buildBrowserTools({ agentId, sandbox }); + Object.assign(tools, browserTools); + } + return tools; } diff --git a/backend/src/tools/kernel/index.ts b/backend/src/tools/kernel/index.ts new file mode 100644 index 0000000..f7168a9 --- /dev/null +++ b/backend/src/tools/kernel/index.ts @@ -0,0 +1,576 @@ +import { z } from 'zod'; +import { tool, zodSchema } from 'ai'; +import type { Sandbox } from '@vercel/sandbox'; +import Kernel from '@onkernel/sdk'; +import { emitStatus } from '../../stream/events'; +import type { ToolCallImage } from '../../db/entities/ToolCall'; + +// Module-level state for browser session per agent +const browserSessions: Map = new Map(); + +// Store console logs and network requests for each agent session +const consoleLogs: Map> = new Map(); +const networkLogs: Map> = new Map(); + +function getKernelClient(): Kernel { + const apiKey = process.env.KERNEL_API_KEY; + if (!apiKey) { + throw new Error('KERNEL_API_KEY environment variable is not set'); + } + return new Kernel({ apiKey }); +} + +export type BrowserToolResult = { + text: string; + images?: ToolCallImage[]; +}; + +export function buildBrowserTools(params: { agentId: number; sandbox: Sandbox }) { + const { agentId, sandbox } = params; + + // Tool schemas + const startDevServerSchema = z.object({ + command: z.string().describe('Command to start the dev server (e.g., "npm run dev", "bun dev")'), + port: z.number().describe('Port the dev server will run on (e.g., 3000)'), + }); + + const createSessionSchema = z.object({ + url: z.string().optional().describe('Optional initial URL to navigate to after creating the browser'), + }); + + const screenshotSchema = z.object({}); + + const executeSchema = z.object({ + code: z.string().describe('Playwright/JavaScript code to execute. Has access to `page`, `context`, and `browser` variables.'), + timeout_sec: z.number().optional().default(60).describe('Execution timeout in seconds'), + }); + + const navigateSchema = z.object({ + url: z.string().describe('URL to navigate to'), + }); + + const clickSchema = z.object({ + selector: z.string().describe('CSS selector for the element to click'), + }); + + const typeSchema = z.object({ + selector: z.string().describe('CSS selector for the input element'), + text: z.string().describe('Text to type into the element'), + }); + + const closeSessionSchema = z.object({}); + + const getConsoleLogsSchema = z.object({ + clear: z.boolean().optional().default(false).describe('Whether to clear the logs after retrieving them'), + }); + + const getNetworkLogsSchema = z.object({ + clear: z.boolean().optional().default(false).describe('Whether to clear the logs after retrieving them'), + }); + + const getPageContentSchema = z.object({ + format: z.enum(['html', 'text']).optional().default('text').describe('Format to return: "html" for full HTML, "text" for visible text only'), + }); + + const waitForPageLoadSchema = z.object({ + selector: z.string().optional().describe('Optional CSS selector to wait for'), + timeout_sec: z.number().optional().default(30).describe('Timeout in seconds'), + }); + + // Tools + const browser_start_dev_server = tool({ + description: 'Start a development server in the sandbox and expose it via a public URL. Use this before browser_create_session to make your app accessible to the browser.', + inputSchema: zodSchema(startDevServerSchema), + execute: async (input): Promise => { + const { command, port } = input; + await emitStatus(agentId, 'running', 'tool_browser_start_dev_server', `Starting dev server: ${command}`, { arguments: input }); + + // Start the dev server in detached mode + await sandbox.runCommand({ + cmd: 'bash', + args: ['-c', command], + detached: true, + }); + + // Get the public URL for the port + const publicUrl = sandbox.domain(port); + + // Poll for server readiness (up to 60 seconds) + const maxAttempts = 30; + let serverReady = false; + for (let attempt = 0; attempt < maxAttempts; attempt++) { + await new Promise((resolve) => setTimeout(resolve, 2000)); + try { + const response = await fetch(publicUrl, { method: 'HEAD', signal: AbortSignal.timeout(5000) }); + if (response.ok || response.status < 500) { + serverReady = true; + break; + } + } catch { + // Server not ready yet, continue polling + } + if (attempt % 5 === 0) { + await emitStatus(agentId, 'running', 'tool_browser_start_dev_server', `Waiting for server to start... (${(attempt + 1) * 2}s)`, { arguments: input }); + } + } + + if (!serverReady) { + return { + text: `Dev server started but may not be ready yet. Public URL: ${publicUrl}\nNote: The server did not respond within 60 seconds. It may still be starting up or there could be an issue with the application.`, + }; + } + + await emitStatus(agentId, 'running', 'tool_browser_start_dev_server', `Dev server started at ${publicUrl}`, { arguments: input }); + + return { + text: `Dev server started successfully and is responding. Public URL: ${publicUrl}`, + }; + }, + }); + + const browser_create_session = tool({ + description: 'Create a new browser session using Kernel.sh. This starts a remote browser that can be controlled via other browser tools. Call browser_start_dev_server first if you need to access an app running in the sandbox.', + inputSchema: zodSchema(createSessionSchema), + execute: async (input): Promise => { + const { url } = input; + await emitStatus(agentId, 'running', 'tool_browser_create_session', 'Creating browser session', { arguments: input }); + + const client = getKernelClient(); + const browserResponse = await client.browsers.create({ + headless: false, + timeout_seconds: 300, // 5 minutes + }); + + const sessionId = browserResponse.session_id; + + // Store the session for this agent + browserSessions.set(agentId, { sessionId, client }); + + // Initialize log storage for this agent + consoleLogs.set(agentId, []); + networkLogs.set(agentId, []); + + // Set up console and network logging via Playwright + await client.browsers.playwright.execute(sessionId, { + code: ` + // Store logs in page context for later retrieval + window.__consoleLogs = window.__consoleLogs || []; + window.__networkLogs = window.__networkLogs || []; + + // Capture console messages + const originalConsole = { log: console.log, warn: console.warn, error: console.error, info: console.info }; + ['log', 'warn', 'error', 'info'].forEach(type => { + console[type] = function(...args) { + window.__consoleLogs.push({ type, text: args.map(a => String(a)).join(' '), timestamp: new Date().toISOString() }); + originalConsole[type].apply(console, args); + }; + }); + + // Capture network requests via Performance API + const observer = new PerformanceObserver((list) => { + for (const entry of list.getEntries()) { + if (entry.entryType === 'resource') { + window.__networkLogs.push({ + method: 'GET', + url: entry.name, + status: 200, + timestamp: new Date().toISOString() + }); + } + } + }); + observer.observe({ entryTypes: ['resource'] }); + `, + timeout_sec: 10, + }); + + let result = `Browser session created. Session ID: ${sessionId}`; + if (browserResponse.browser_live_view_url) { + result += `\nLive view URL: ${browserResponse.browser_live_view_url}`; + } + result += `\nConsole and network logging enabled. Use browser_get_console_logs and browser_get_network_logs to retrieve logs.`; + + // Navigate to initial URL if provided + if (url) { + await client.browsers.playwright.execute(sessionId, { + code: `await page.goto('${url}', { waitUntil: 'domcontentloaded', timeout: 30000 });`, + timeout_sec: 35, + }); + // Wait a bit more for JS to execute + await client.browsers.playwright.execute(sessionId, { + code: `await page.waitForTimeout(2000);`, + timeout_sec: 10, + }); + result += `\nNavigated to: ${url}`; + } + + await emitStatus(agentId, 'running', 'tool_browser_create_session', result, { arguments: input }); + + return { text: result }; + }, + }); + + const browser_screenshot = tool({ + description: 'Capture a screenshot of the current browser page. The screenshot will be stored and can be viewed in the tool call history.', + inputSchema: zodSchema(screenshotSchema), + execute: async (input): Promise => { + await emitStatus(agentId, 'running', 'tool_browser_screenshot', 'Capturing screenshot', { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + // Capture screenshot - returns Response with blob + const response = await client.browsers.computer.captureScreenshot(sessionId); + const blob = await response.blob(); + const arrayBuffer = await blob.arrayBuffer(); + const base64 = Buffer.from(arrayBuffer).toString('base64'); + + const image: ToolCallImage = { + data: base64, + mimeType: 'image/png', + }; + + await emitStatus(agentId, 'running', 'tool_browser_screenshot', 'Screenshot captured', { arguments: input }); + + return { + text: 'Screenshot captured successfully.', + images: [image], + }; + }, + }); + + const browser_execute = tool({ + description: 'Execute arbitrary Playwright code in the browser. Has access to `page`, `context`, and `browser` variables. Use this for complex interactions not covered by other tools.', + inputSchema: zodSchema(executeSchema), + execute: async (input): Promise => { + const { code, timeout_sec } = input; + await emitStatus(agentId, 'running', 'tool_browser_execute', `Executing Playwright code`, { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + const result = await client.browsers.playwright.execute(sessionId, { + code, + timeout_sec: timeout_sec || 60, + }); + + await emitStatus(agentId, 'running', 'tool_browser_execute', 'Code executed', { arguments: input }); + + return { + text: result.result !== undefined ? `Execution result: ${JSON.stringify(result.result)}` : 'Code executed successfully.', + }; + }, + }); + + const browser_navigate = tool({ + description: 'Navigate the browser to a specific URL. Waits for page to load.', + inputSchema: zodSchema(navigateSchema), + execute: async (input): Promise => { + const { url } = input; + await emitStatus(agentId, 'running', 'tool_browser_navigate', `Navigating to ${url}`, { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + // Use domcontentloaded first, then wait for additional JS execution + await client.browsers.playwright.execute(sessionId, { + code: ` + await page.goto('${url}', { waitUntil: 'domcontentloaded', timeout: 30000 }); + // Wait for any pending JS to execute + await page.waitForTimeout(2000); + // Try to wait for network idle, but don't fail if it times out + try { + await page.waitForLoadState('networkidle', { timeout: 5000 }); + } catch (e) { + // Page may have continuous network activity, that's okay + } + `, + timeout_sec: 45, + }); + + await emitStatus(agentId, 'running', 'tool_browser_navigate', `Navigated to ${url}`, { arguments: input }); + + return { text: `Successfully navigated to ${url}` }; + }, + }); + + const browser_click = tool({ + description: 'Click on an element in the browser using a CSS selector.', + inputSchema: zodSchema(clickSchema), + execute: async (input): Promise => { + const { selector } = input; + await emitStatus(agentId, 'running', 'tool_browser_click', `Clicking ${selector}`, { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + await client.browsers.playwright.execute(sessionId, { + code: `await page.click('${selector.replace(/'/g, "\\'")}');`, + timeout_sec: 30, + }); + + await emitStatus(agentId, 'running', 'tool_browser_click', `Clicked ${selector}`, { arguments: input }); + + return { text: `Successfully clicked on element: ${selector}` }; + }, + }); + + const browser_type = tool({ + description: 'Type text into an input element in the browser.', + inputSchema: zodSchema(typeSchema), + execute: async (input): Promise => { + const { selector, text } = input; + await emitStatus(agentId, 'running', 'tool_browser_type', `Typing into ${selector}`, { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + await client.browsers.playwright.execute(sessionId, { + code: `await page.fill('${selector.replace(/'/g, "\\'")}', '${text.replace(/'/g, "\\'")}');`, + timeout_sec: 30, + }); + + await emitStatus(agentId, 'running', 'tool_browser_type', `Typed into ${selector}`, { arguments: input }); + + return { text: `Successfully typed "${text}" into element: ${selector}` }; + }, + }); + + const browser_close_session = tool({ + description: 'Close the current browser session and clean up resources.', + inputSchema: zodSchema(closeSessionSchema), + execute: async (input): Promise => { + await emitStatus(agentId, 'running', 'tool_browser_close_session', 'Closing browser session', { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'No browser session to close.' }; + } + + const { sessionId, client } = session; + + await client.browsers.deleteByID(sessionId); + browserSessions.delete(agentId); + consoleLogs.delete(agentId); + networkLogs.delete(agentId); + + await emitStatus(agentId, 'running', 'tool_browser_close_session', 'Browser session closed', { arguments: input }); + + return { text: 'Browser session closed successfully.' }; + }, + }); + + const browser_get_console_logs = tool({ + description: 'Get console logs (log, warn, error, info) captured from the browser. Useful for debugging JavaScript errors and application behavior.', + inputSchema: zodSchema(getConsoleLogsSchema), + execute: async (input): Promise => { + const { clear } = input; + await emitStatus(agentId, 'running', 'tool_browser_get_console_logs', 'Retrieving console logs', { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + // Retrieve console logs from the page + const result = await client.browsers.playwright.execute(sessionId, { + code: ` + const logs = window.__consoleLogs || []; + if (${clear}) { + window.__consoleLogs = []; + } + return logs; + `, + timeout_sec: 10, + }); + + const logs = (result.result as Array<{ type: string; text: string; timestamp: string }>) || []; + + if (logs.length === 0) { + return { text: 'No console logs captured.' }; + } + + const formattedLogs = logs + .map((log) => `[${log.timestamp}] [${log.type.toUpperCase()}] ${log.text}`) + .join('\n'); + + await emitStatus(agentId, 'running', 'tool_browser_get_console_logs', `Retrieved ${logs.length} console logs`, { arguments: input }); + + return { text: `Console Logs (${logs.length} entries):\n${formattedLogs}` }; + }, + }); + + const browser_get_network_logs = tool({ + description: 'Get network request logs captured from the browser. Useful for debugging API calls, failed requests, and resource loading.', + inputSchema: zodSchema(getNetworkLogsSchema), + execute: async (input): Promise => { + const { clear } = input; + await emitStatus(agentId, 'running', 'tool_browser_get_network_logs', 'Retrieving network logs', { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + // Retrieve network logs from the page + const result = await client.browsers.playwright.execute(sessionId, { + code: ` + const logs = window.__networkLogs || []; + if (${clear}) { + window.__networkLogs = []; + } + return logs; + `, + timeout_sec: 10, + }); + + const logs = (result.result as Array<{ method: string; url: string; status?: number; timestamp: string }>) || []; + + if (logs.length === 0) { + return { text: 'No network logs captured.' }; + } + + const formattedLogs = logs + .map((log) => `[${log.timestamp}] ${log.method} ${log.url} ${log.status ? `(${log.status})` : ''}`) + .join('\n'); + + await emitStatus(agentId, 'running', 'tool_browser_get_network_logs', `Retrieved ${logs.length} network logs`, { arguments: input }); + + return { text: `Network Logs (${logs.length} entries):\n${formattedLogs}` }; + }, + }); + + const browser_get_page_content = tool({ + description: 'Get the current page content as HTML or visible text. Useful for understanding what the browser is displaying and debugging rendering issues.', + inputSchema: zodSchema(getPageContentSchema), + execute: async (input): Promise => { + const { format } = input; + await emitStatus(agentId, 'running', 'tool_browser_get_page_content', `Getting page content as ${format}`, { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + const code = format === 'html' + ? `return await page.content();` + : `return await page.innerText('body');`; + + const result = await client.browsers.playwright.execute(sessionId, { + code, + timeout_sec: 15, + }); + + const content = (result.result as string) || ''; + + // Truncate if too long + const maxLength = 50000; + const truncated = content.length > maxLength; + const displayContent = truncated ? content.substring(0, maxLength) + '\n\n... (content truncated)' : content; + + await emitStatus(agentId, 'running', 'tool_browser_get_page_content', `Retrieved page ${format}`, { arguments: input }); + + return { text: `Page ${format.toUpperCase()} Content:\n${displayContent}` }; + }, + }); + + const browser_wait_for_page = tool({ + description: 'Wait for the page to finish loading or for a specific element to appear. Use this after navigation if you need to ensure content is fully rendered.', + inputSchema: zodSchema(waitForPageLoadSchema), + execute: async (input): Promise => { + const { selector, timeout_sec } = input; + await emitStatus(agentId, 'running', 'tool_browser_wait_for_page', selector ? `Waiting for ${selector}` : 'Waiting for page load', { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + try { + if (selector) { + await client.browsers.playwright.execute(sessionId, { + code: `await page.waitForSelector('${selector.replace(/'/g, "\\'")}', { timeout: ${(timeout_sec || 30) * 1000} });`, + timeout_sec: (timeout_sec || 30) + 5, + }); + return { text: `Element "${selector}" found and visible.` }; + } else { + await client.browsers.playwright.execute(sessionId, { + code: ` + await page.waitForLoadState('domcontentloaded', { timeout: ${(timeout_sec || 30) * 1000} }); + await page.waitForTimeout(1000); + try { + await page.waitForLoadState('networkidle', { timeout: 5000 }); + } catch (e) { + // Network may not be idle, that's okay + } + `, + timeout_sec: (timeout_sec || 30) + 10, + }); + return { text: 'Page finished loading.' }; + } + } catch (error) { + const message = error instanceof Error ? error.message : 'Unknown error'; + return { text: `Timeout waiting for page: ${message}` }; + } + }, + }); + + return { + browser_start_dev_server, + browser_create_session, + browser_screenshot, + browser_execute, + browser_navigate, + browser_click, + browser_type, + browser_close_session, + browser_get_console_logs, + browser_get_network_logs, + browser_get_page_content, + browser_wait_for_page, + }; +} + +// Cleanup function to be called when agent workflow ends +export async function cleanupBrowserSession(agentId: number): Promise { + const session = browserSessions.get(agentId); + if (session) { + try { + await session.client.browsers.deleteByID(session.sessionId); + } catch { + // Ignore cleanup errors + } + browserSessions.delete(agentId); + } + // Clean up log storage + consoleLogs.delete(agentId); + networkLogs.delete(agentId); +} diff --git a/backend/src/workflows/agent.ts b/backend/src/workflows/agent.ts index 715df4e..653c285 100644 --- a/backend/src/workflows/agent.ts +++ b/backend/src/workflows/agent.ts @@ -38,7 +38,7 @@ export async function runOrchestratorAgentWorkflow(payload: AgentJobPayload) { const agent = await loadAgent(payload.agentId); const { repositoryFullName, token } = await validateAndGetToken(agent, payload.repositoryFullName); - sandbox = await prepareSandbox(agent, token, repositoryFullName, payload.baseBranch); + sandbox = await prepareSandbox(agent, token, repositoryFullName, payload.baseBranch, payload.toolSlugs); if (!sandbox) throw new Error('Failed to create sandbox'); sandboxStartTime = Date.now(); @@ -55,13 +55,13 @@ export async function runOrchestratorAgentWorkflow(payload: AgentJobPayload) { const sandboxDurationMs = Date.now() - sandboxStartTime; await saveAgentResponse(agent, response, usageAccumulator, sandboxDurationMs); - await cleanupSandbox(sandbox); + await cleanupSandbox(sandbox, agent.id); await markAgentComplete(agent.id); } catch (error: unknown) { if (sandbox) { try { - await cleanupSandbox(sandbox); + await cleanupSandbox(sandbox, payload.agentId); } catch { // Ignore cleanup errors } @@ -82,7 +82,7 @@ export async function runAgentWorkflow(payload: AgentJobPayload) { const agent = await loadAgent(payload.agentId); const { repositoryFullName, token } = await validateAndGetToken(agent, payload.repositoryFullName); - sandbox = await prepareSandbox(agent, token, repositoryFullName, payload.baseBranch); + sandbox = await prepareSandbox(agent, token, repositoryFullName, payload.baseBranch, payload.toolSlugs); if (!sandbox) throw new Error('Failed to create sandbox'); sandboxStartTime = Date.now(); @@ -99,20 +99,20 @@ export async function runAgentWorkflow(payload: AgentJobPayload) { await saveAgentResponse(agent, response, usageAccumulator, sandboxDurationMs); if (payload.isOrchestratorAgent) { - await cleanupSandbox(sandbox); + await cleanupSandbox(sandbox, agent.id); await markAgentComplete(agent.id); return; } await commitChangesIfNeeded(sandbox, agent.id, payload.prompt); - await cleanupSandbox(sandbox); + await cleanupSandbox(sandbox, agent.id); await markAgentComplete(agent.id); } catch (error: unknown) { if (sandbox) { try { - await cleanupSandbox(sandbox); + await cleanupSandbox(sandbox, payload.agentId); } catch { // Ignore cleanup errors } diff --git a/backend/src/workflows/helpers/agents.ts b/backend/src/workflows/helpers/agents.ts index ee5f6db..8529260 100644 --- a/backend/src/workflows/helpers/agents.ts +++ b/backend/src/workflows/helpers/agents.ts @@ -3,9 +3,10 @@ import { AppDataSource } from '../../db/data-source'; import { Agent } from '../../db/entities/Agent'; import { IntegrationConnection } from '../../db/entities/IntegrationConnection'; import { Message, type SenderType } from '../../db/entities/Message'; -import { ToolCall } from '../../db/entities/ToolCall'; +import { ToolCall, type ToolCallImage } from '../../db/entities/ToolCall'; import { updateSlackWorkspaceStatus } from '../../slack/notifications'; import type { TokenUsageAccumulator } from '../llm'; +import type { BrowserToolResult } from '../../tools/kernel/index'; export async function getAgentById(agentId: number) { return AppDataSource.getRepository(Agent).findOne({ @@ -59,19 +60,34 @@ export async function saveAgentActivity( toolName: 'reasoning', arguments: {}, result: reasoningText, + images: [], status: 'success', }) ); } for (const toolResult of step.toolResults) { const toolArguments = (toolResult.input ?? {}) as Record; + + // Extract images if present in output (for browser tools) + const output = toolResult.output as BrowserToolResult | string | undefined; + let resultText: string; + let images: ToolCallImage[] = []; + + if (typeof output === 'object' && output !== null && 'text' in output) { + resultText = output.text || ''; + images = output.images || []; + } else { + resultText = (output as string) || ''; + } + savedToolCalls.push( toolCallRepository.create({ agent, message, toolName: toolResult.toolName, arguments: toolArguments, - result: (toolResult.output as string) || '', + result: resultText, + images, status: 'success', }) ); diff --git a/backend/src/workflows/helpers/sandbox.ts b/backend/src/workflows/helpers/sandbox.ts index 4b7f728..855e400 100644 --- a/backend/src/workflows/helpers/sandbox.ts +++ b/backend/src/workflows/helpers/sandbox.ts @@ -3,7 +3,16 @@ import { Sandbox } from '@vercel/sandbox'; import { Agent } from '../../db/entities/Agent'; import { updateAgent } from './agents'; -export async function createSandbox(agent: Agent, token: string, repositoryFullName: string, baseBranch: string): Promise { +// Common ports for dev servers (Vercel Sandbox allows up to 4 ports) +export const DEFAULT_BROWSER_PORTS = [3000, 3001, 5173]; + +export async function createSandbox( + agent: Agent, + token: string, + repositoryFullName: string, + baseBranch: string, + ports?: number[] +): Promise { const sandbox = await Sandbox.create({ token: process.env.VERCEL_TOKEN, teamId: process.env.VERCEL_TEAM_ID, @@ -17,6 +26,7 @@ export async function createSandbox(agent: Agent, token: string, repositoryFullN runtime: process.env.VERCEL_RUNTIME || 'node22', timeout: 5 * 60 * 1000, resources: { vcpus: 2 }, + ports: ports || [], }); await updateAgent(agent, { sandboxId: sandbox.sandboxId }); diff --git a/backend/src/workflows/steps.ts b/backend/src/workflows/steps.ts index 05644f1..9d2cfc5 100644 --- a/backend/src/workflows/steps.ts +++ b/backend/src/workflows/steps.ts @@ -7,10 +7,11 @@ import { AppDataSource } from '../db/data-source'; import { emitDone, emitError, emitStatus } from '../stream/events'; import { getAgentById, saveMessage, saveAgentActivity, updateAgent } from './helpers/agents'; import { commitAndPush, generateBranchName, getGithubTokenForUser } from './helpers/github'; -import { createSandbox } from './helpers/sandbox'; +import { createSandbox, DEFAULT_BROWSER_PORTS } from './helpers/sandbox'; import type { runAgentLLM, runOrchestratorAgentLLM, TokenUsageAccumulator } from './llm'; import { calculateCostMicrodollars } from '../payment/model-pricing'; import { incrementTokenCostMicrodollars, incrementSandboxTimeSeconds } from '../payment/usage'; +import { cleanupBrowserSession } from '../tools/kernel/index'; export async function loadAgent(agentId: number) { const agent = await getAgentById(agentId); @@ -34,11 +35,20 @@ export async function validateAndGetToken(agent: Agent, repositoryFullName: stri return { repositoryFullName: repoName, token }; } -export async function prepareSandbox(agent: Agent, token: string, repositoryFullName: string, baseBranch: string) { +export async function prepareSandbox( + agent: Agent, + token: string, + repositoryFullName: string, + baseBranch: string, + toolSlugs?: string[] +) { await emitStatus(agent.id, 'starting', 'agent_init', 'preparing sandbox'); + // Expose ports if browser tools are enabled + const ports = toolSlugs?.includes('kernel/browser') ? DEFAULT_BROWSER_PORTS : undefined; + try { - const sandbox = await createSandbox(agent, token, repositoryFullName, baseBranch); + const sandbox = await createSandbox(agent, token, repositoryFullName, baseBranch, ports); return sandbox; } catch (err: unknown) { const message = err instanceof Error ? err.message : 'Failed to create sandbox'; @@ -122,7 +132,11 @@ export async function commitChangesIfNeeded(sandbox: Sandbox, agentId: number, p } } -export async function cleanupSandbox(sandbox: Sandbox) { +export async function cleanupSandbox(sandbox: Sandbox, agentId?: number) { + // Cleanup browser session if one exists + if (agentId !== undefined) { + await cleanupBrowserSession(agentId); + } await sandbox.stop(); } From 5167be3e9aae4257d40dc47bf8778798c584de4d Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Wed, 14 Jan 2026 18:46:23 -0600 Subject: [PATCH 02/14] clean up kernel tools --- backend/src/tools/kernel/index.ts | 581 +----------------- backend/src/tools/kernel/session.ts | 24 + backend/src/tools/kernel/tools/click.ts | 37 ++ .../src/tools/kernel/tools/closeSession.ts | 34 + .../src/tools/kernel/tools/createSession.ts | 90 +++ backend/src/tools/kernel/tools/execute.ts | 41 ++ .../src/tools/kernel/tools/getConsoleLogs.ts | 51 ++ .../src/tools/kernel/tools/getNetworkLogs.ts | 51 ++ .../src/tools/kernel/tools/getPageContent.ts | 46 ++ backend/src/tools/kernel/tools/navigate.ts | 47 ++ backend/src/tools/kernel/tools/screenshot.ts | 43 ++ .../src/tools/kernel/tools/startDevServer.ts | 64 ++ backend/src/tools/kernel/tools/type.ts | 38 ++ backend/src/tools/kernel/tools/waitForPage.ts | 59 ++ backend/src/workflows/helpers/sandbox.ts | 8 +- backend/src/workflows/steps.ts | 8 +- 16 files changed, 654 insertions(+), 568 deletions(-) create mode 100644 backend/src/tools/kernel/session.ts create mode 100644 backend/src/tools/kernel/tools/click.ts create mode 100644 backend/src/tools/kernel/tools/closeSession.ts create mode 100644 backend/src/tools/kernel/tools/createSession.ts create mode 100644 backend/src/tools/kernel/tools/execute.ts create mode 100644 backend/src/tools/kernel/tools/getConsoleLogs.ts create mode 100644 backend/src/tools/kernel/tools/getNetworkLogs.ts create mode 100644 backend/src/tools/kernel/tools/getPageContent.ts create mode 100644 backend/src/tools/kernel/tools/navigate.ts create mode 100644 backend/src/tools/kernel/tools/screenshot.ts create mode 100644 backend/src/tools/kernel/tools/startDevServer.ts create mode 100644 backend/src/tools/kernel/tools/type.ts create mode 100644 backend/src/tools/kernel/tools/waitForPage.ts diff --git a/backend/src/tools/kernel/index.ts b/backend/src/tools/kernel/index.ts index f7168a9..2957f29 100644 --- a/backend/src/tools/kernel/index.ts +++ b/backend/src/tools/kernel/index.ts @@ -1,565 +1,39 @@ -import { z } from 'zod'; -import { tool, zodSchema } from 'ai'; import type { Sandbox } from '@vercel/sandbox'; -import Kernel from '@onkernel/sdk'; -import { emitStatus } from '../../stream/events'; -import type { ToolCallImage } from '../../db/entities/ToolCall'; - -// Module-level state for browser session per agent -const browserSessions: Map = new Map(); - -// Store console logs and network requests for each agent session -const consoleLogs: Map> = new Map(); -const networkLogs: Map> = new Map(); - -function getKernelClient(): Kernel { - const apiKey = process.env.KERNEL_API_KEY; - if (!apiKey) { - throw new Error('KERNEL_API_KEY environment variable is not set'); - } - return new Kernel({ apiKey }); -} - -export type BrowserToolResult = { - text: string; - images?: ToolCallImage[]; -}; +import { browserSessions, consoleLogs, networkLogs } from './session'; +import { buildStartDevServerTool } from './tools/startDevServer'; +import { buildCreateSessionTool } from './tools/createSession'; +import { buildScreenshotTool } from './tools/screenshot'; +import { buildExecuteTool } from './tools/execute'; +import { buildNavigateTool } from './tools/navigate'; +import { buildClickTool } from './tools/click'; +import { buildTypeTool } from './tools/type'; +import { buildCloseSessionTool } from './tools/closeSession'; +import { buildGetConsoleLogsTool } from './tools/getConsoleLogs'; +import { buildGetNetworkLogsTool } from './tools/getNetworkLogs'; +import { buildGetPageContentTool } from './tools/getPageContent'; +import { buildWaitForPageTool } from './tools/waitForPage'; + +export type { BrowserToolResult } from './session'; export function buildBrowserTools(params: { agentId: number; sandbox: Sandbox }) { const { agentId, sandbox } = params; - // Tool schemas - const startDevServerSchema = z.object({ - command: z.string().describe('Command to start the dev server (e.g., "npm run dev", "bun dev")'), - port: z.number().describe('Port the dev server will run on (e.g., 3000)'), - }); - - const createSessionSchema = z.object({ - url: z.string().optional().describe('Optional initial URL to navigate to after creating the browser'), - }); - - const screenshotSchema = z.object({}); - - const executeSchema = z.object({ - code: z.string().describe('Playwright/JavaScript code to execute. Has access to `page`, `context`, and `browser` variables.'), - timeout_sec: z.number().optional().default(60).describe('Execution timeout in seconds'), - }); - - const navigateSchema = z.object({ - url: z.string().describe('URL to navigate to'), - }); - - const clickSchema = z.object({ - selector: z.string().describe('CSS selector for the element to click'), - }); - - const typeSchema = z.object({ - selector: z.string().describe('CSS selector for the input element'), - text: z.string().describe('Text to type into the element'), - }); - - const closeSessionSchema = z.object({}); - - const getConsoleLogsSchema = z.object({ - clear: z.boolean().optional().default(false).describe('Whether to clear the logs after retrieving them'), - }); - - const getNetworkLogsSchema = z.object({ - clear: z.boolean().optional().default(false).describe('Whether to clear the logs after retrieving them'), - }); - - const getPageContentSchema = z.object({ - format: z.enum(['html', 'text']).optional().default('text').describe('Format to return: "html" for full HTML, "text" for visible text only'), - }); - - const waitForPageLoadSchema = z.object({ - selector: z.string().optional().describe('Optional CSS selector to wait for'), - timeout_sec: z.number().optional().default(30).describe('Timeout in seconds'), - }); - - // Tools - const browser_start_dev_server = tool({ - description: 'Start a development server in the sandbox and expose it via a public URL. Use this before browser_create_session to make your app accessible to the browser.', - inputSchema: zodSchema(startDevServerSchema), - execute: async (input): Promise => { - const { command, port } = input; - await emitStatus(agentId, 'running', 'tool_browser_start_dev_server', `Starting dev server: ${command}`, { arguments: input }); - - // Start the dev server in detached mode - await sandbox.runCommand({ - cmd: 'bash', - args: ['-c', command], - detached: true, - }); - - // Get the public URL for the port - const publicUrl = sandbox.domain(port); - - // Poll for server readiness (up to 60 seconds) - const maxAttempts = 30; - let serverReady = false; - for (let attempt = 0; attempt < maxAttempts; attempt++) { - await new Promise((resolve) => setTimeout(resolve, 2000)); - try { - const response = await fetch(publicUrl, { method: 'HEAD', signal: AbortSignal.timeout(5000) }); - if (response.ok || response.status < 500) { - serverReady = true; - break; - } - } catch { - // Server not ready yet, continue polling - } - if (attempt % 5 === 0) { - await emitStatus(agentId, 'running', 'tool_browser_start_dev_server', `Waiting for server to start... (${(attempt + 1) * 2}s)`, { arguments: input }); - } - } - - if (!serverReady) { - return { - text: `Dev server started but may not be ready yet. Public URL: ${publicUrl}\nNote: The server did not respond within 60 seconds. It may still be starting up or there could be an issue with the application.`, - }; - } - - await emitStatus(agentId, 'running', 'tool_browser_start_dev_server', `Dev server started at ${publicUrl}`, { arguments: input }); - - return { - text: `Dev server started successfully and is responding. Public URL: ${publicUrl}`, - }; - }, - }); - - const browser_create_session = tool({ - description: 'Create a new browser session using Kernel.sh. This starts a remote browser that can be controlled via other browser tools. Call browser_start_dev_server first if you need to access an app running in the sandbox.', - inputSchema: zodSchema(createSessionSchema), - execute: async (input): Promise => { - const { url } = input; - await emitStatus(agentId, 'running', 'tool_browser_create_session', 'Creating browser session', { arguments: input }); - - const client = getKernelClient(); - const browserResponse = await client.browsers.create({ - headless: false, - timeout_seconds: 300, // 5 minutes - }); - - const sessionId = browserResponse.session_id; - - // Store the session for this agent - browserSessions.set(agentId, { sessionId, client }); - - // Initialize log storage for this agent - consoleLogs.set(agentId, []); - networkLogs.set(agentId, []); - - // Set up console and network logging via Playwright - await client.browsers.playwright.execute(sessionId, { - code: ` - // Store logs in page context for later retrieval - window.__consoleLogs = window.__consoleLogs || []; - window.__networkLogs = window.__networkLogs || []; - - // Capture console messages - const originalConsole = { log: console.log, warn: console.warn, error: console.error, info: console.info }; - ['log', 'warn', 'error', 'info'].forEach(type => { - console[type] = function(...args) { - window.__consoleLogs.push({ type, text: args.map(a => String(a)).join(' '), timestamp: new Date().toISOString() }); - originalConsole[type].apply(console, args); - }; - }); - - // Capture network requests via Performance API - const observer = new PerformanceObserver((list) => { - for (const entry of list.getEntries()) { - if (entry.entryType === 'resource') { - window.__networkLogs.push({ - method: 'GET', - url: entry.name, - status: 200, - timestamp: new Date().toISOString() - }); - } - } - }); - observer.observe({ entryTypes: ['resource'] }); - `, - timeout_sec: 10, - }); - - let result = `Browser session created. Session ID: ${sessionId}`; - if (browserResponse.browser_live_view_url) { - result += `\nLive view URL: ${browserResponse.browser_live_view_url}`; - } - result += `\nConsole and network logging enabled. Use browser_get_console_logs and browser_get_network_logs to retrieve logs.`; - - // Navigate to initial URL if provided - if (url) { - await client.browsers.playwright.execute(sessionId, { - code: `await page.goto('${url}', { waitUntil: 'domcontentloaded', timeout: 30000 });`, - timeout_sec: 35, - }); - // Wait a bit more for JS to execute - await client.browsers.playwright.execute(sessionId, { - code: `await page.waitForTimeout(2000);`, - timeout_sec: 10, - }); - result += `\nNavigated to: ${url}`; - } - - await emitStatus(agentId, 'running', 'tool_browser_create_session', result, { arguments: input }); - - return { text: result }; - }, - }); - - const browser_screenshot = tool({ - description: 'Capture a screenshot of the current browser page. The screenshot will be stored and can be viewed in the tool call history.', - inputSchema: zodSchema(screenshotSchema), - execute: async (input): Promise => { - await emitStatus(agentId, 'running', 'tool_browser_screenshot', 'Capturing screenshot', { arguments: input }); - - const session = browserSessions.get(agentId); - if (!session) { - return { text: 'Error: No browser session found. Call browser_create_session first.' }; - } - - const { sessionId, client } = session; - - // Capture screenshot - returns Response with blob - const response = await client.browsers.computer.captureScreenshot(sessionId); - const blob = await response.blob(); - const arrayBuffer = await blob.arrayBuffer(); - const base64 = Buffer.from(arrayBuffer).toString('base64'); - - const image: ToolCallImage = { - data: base64, - mimeType: 'image/png', - }; - - await emitStatus(agentId, 'running', 'tool_browser_screenshot', 'Screenshot captured', { arguments: input }); - - return { - text: 'Screenshot captured successfully.', - images: [image], - }; - }, - }); - - const browser_execute = tool({ - description: 'Execute arbitrary Playwright code in the browser. Has access to `page`, `context`, and `browser` variables. Use this for complex interactions not covered by other tools.', - inputSchema: zodSchema(executeSchema), - execute: async (input): Promise => { - const { code, timeout_sec } = input; - await emitStatus(agentId, 'running', 'tool_browser_execute', `Executing Playwright code`, { arguments: input }); - - const session = browserSessions.get(agentId); - if (!session) { - return { text: 'Error: No browser session found. Call browser_create_session first.' }; - } - - const { sessionId, client } = session; - - const result = await client.browsers.playwright.execute(sessionId, { - code, - timeout_sec: timeout_sec || 60, - }); - - await emitStatus(agentId, 'running', 'tool_browser_execute', 'Code executed', { arguments: input }); - - return { - text: result.result !== undefined ? `Execution result: ${JSON.stringify(result.result)}` : 'Code executed successfully.', - }; - }, - }); - - const browser_navigate = tool({ - description: 'Navigate the browser to a specific URL. Waits for page to load.', - inputSchema: zodSchema(navigateSchema), - execute: async (input): Promise => { - const { url } = input; - await emitStatus(agentId, 'running', 'tool_browser_navigate', `Navigating to ${url}`, { arguments: input }); - - const session = browserSessions.get(agentId); - if (!session) { - return { text: 'Error: No browser session found. Call browser_create_session first.' }; - } - - const { sessionId, client } = session; - - // Use domcontentloaded first, then wait for additional JS execution - await client.browsers.playwright.execute(sessionId, { - code: ` - await page.goto('${url}', { waitUntil: 'domcontentloaded', timeout: 30000 }); - // Wait for any pending JS to execute - await page.waitForTimeout(2000); - // Try to wait for network idle, but don't fail if it times out - try { - await page.waitForLoadState('networkidle', { timeout: 5000 }); - } catch (e) { - // Page may have continuous network activity, that's okay - } - `, - timeout_sec: 45, - }); - - await emitStatus(agentId, 'running', 'tool_browser_navigate', `Navigated to ${url}`, { arguments: input }); - - return { text: `Successfully navigated to ${url}` }; - }, - }); - - const browser_click = tool({ - description: 'Click on an element in the browser using a CSS selector.', - inputSchema: zodSchema(clickSchema), - execute: async (input): Promise => { - const { selector } = input; - await emitStatus(agentId, 'running', 'tool_browser_click', `Clicking ${selector}`, { arguments: input }); - - const session = browserSessions.get(agentId); - if (!session) { - return { text: 'Error: No browser session found. Call browser_create_session first.' }; - } - - const { sessionId, client } = session; - - await client.browsers.playwright.execute(sessionId, { - code: `await page.click('${selector.replace(/'/g, "\\'")}');`, - timeout_sec: 30, - }); - - await emitStatus(agentId, 'running', 'tool_browser_click', `Clicked ${selector}`, { arguments: input }); - - return { text: `Successfully clicked on element: ${selector}` }; - }, - }); - - const browser_type = tool({ - description: 'Type text into an input element in the browser.', - inputSchema: zodSchema(typeSchema), - execute: async (input): Promise => { - const { selector, text } = input; - await emitStatus(agentId, 'running', 'tool_browser_type', `Typing into ${selector}`, { arguments: input }); - - const session = browserSessions.get(agentId); - if (!session) { - return { text: 'Error: No browser session found. Call browser_create_session first.' }; - } - - const { sessionId, client } = session; - - await client.browsers.playwright.execute(sessionId, { - code: `await page.fill('${selector.replace(/'/g, "\\'")}', '${text.replace(/'/g, "\\'")}');`, - timeout_sec: 30, - }); - - await emitStatus(agentId, 'running', 'tool_browser_type', `Typed into ${selector}`, { arguments: input }); - - return { text: `Successfully typed "${text}" into element: ${selector}` }; - }, - }); - - const browser_close_session = tool({ - description: 'Close the current browser session and clean up resources.', - inputSchema: zodSchema(closeSessionSchema), - execute: async (input): Promise => { - await emitStatus(agentId, 'running', 'tool_browser_close_session', 'Closing browser session', { arguments: input }); - - const session = browserSessions.get(agentId); - if (!session) { - return { text: 'No browser session to close.' }; - } - - const { sessionId, client } = session; - - await client.browsers.deleteByID(sessionId); - browserSessions.delete(agentId); - consoleLogs.delete(agentId); - networkLogs.delete(agentId); - - await emitStatus(agentId, 'running', 'tool_browser_close_session', 'Browser session closed', { arguments: input }); - - return { text: 'Browser session closed successfully.' }; - }, - }); - - const browser_get_console_logs = tool({ - description: 'Get console logs (log, warn, error, info) captured from the browser. Useful for debugging JavaScript errors and application behavior.', - inputSchema: zodSchema(getConsoleLogsSchema), - execute: async (input): Promise => { - const { clear } = input; - await emitStatus(agentId, 'running', 'tool_browser_get_console_logs', 'Retrieving console logs', { arguments: input }); - - const session = browserSessions.get(agentId); - if (!session) { - return { text: 'Error: No browser session found. Call browser_create_session first.' }; - } - - const { sessionId, client } = session; - - // Retrieve console logs from the page - const result = await client.browsers.playwright.execute(sessionId, { - code: ` - const logs = window.__consoleLogs || []; - if (${clear}) { - window.__consoleLogs = []; - } - return logs; - `, - timeout_sec: 10, - }); - - const logs = (result.result as Array<{ type: string; text: string; timestamp: string }>) || []; - - if (logs.length === 0) { - return { text: 'No console logs captured.' }; - } - - const formattedLogs = logs - .map((log) => `[${log.timestamp}] [${log.type.toUpperCase()}] ${log.text}`) - .join('\n'); - - await emitStatus(agentId, 'running', 'tool_browser_get_console_logs', `Retrieved ${logs.length} console logs`, { arguments: input }); - - return { text: `Console Logs (${logs.length} entries):\n${formattedLogs}` }; - }, - }); - - const browser_get_network_logs = tool({ - description: 'Get network request logs captured from the browser. Useful for debugging API calls, failed requests, and resource loading.', - inputSchema: zodSchema(getNetworkLogsSchema), - execute: async (input): Promise => { - const { clear } = input; - await emitStatus(agentId, 'running', 'tool_browser_get_network_logs', 'Retrieving network logs', { arguments: input }); - - const session = browserSessions.get(agentId); - if (!session) { - return { text: 'Error: No browser session found. Call browser_create_session first.' }; - } - - const { sessionId, client } = session; - - // Retrieve network logs from the page - const result = await client.browsers.playwright.execute(sessionId, { - code: ` - const logs = window.__networkLogs || []; - if (${clear}) { - window.__networkLogs = []; - } - return logs; - `, - timeout_sec: 10, - }); - - const logs = (result.result as Array<{ method: string; url: string; status?: number; timestamp: string }>) || []; - - if (logs.length === 0) { - return { text: 'No network logs captured.' }; - } - - const formattedLogs = logs - .map((log) => `[${log.timestamp}] ${log.method} ${log.url} ${log.status ? `(${log.status})` : ''}`) - .join('\n'); - - await emitStatus(agentId, 'running', 'tool_browser_get_network_logs', `Retrieved ${logs.length} network logs`, { arguments: input }); - - return { text: `Network Logs (${logs.length} entries):\n${formattedLogs}` }; - }, - }); - - const browser_get_page_content = tool({ - description: 'Get the current page content as HTML or visible text. Useful for understanding what the browser is displaying and debugging rendering issues.', - inputSchema: zodSchema(getPageContentSchema), - execute: async (input): Promise => { - const { format } = input; - await emitStatus(agentId, 'running', 'tool_browser_get_page_content', `Getting page content as ${format}`, { arguments: input }); - - const session = browserSessions.get(agentId); - if (!session) { - return { text: 'Error: No browser session found. Call browser_create_session first.' }; - } - - const { sessionId, client } = session; - - const code = format === 'html' - ? `return await page.content();` - : `return await page.innerText('body');`; - - const result = await client.browsers.playwright.execute(sessionId, { - code, - timeout_sec: 15, - }); - - const content = (result.result as string) || ''; - - // Truncate if too long - const maxLength = 50000; - const truncated = content.length > maxLength; - const displayContent = truncated ? content.substring(0, maxLength) + '\n\n... (content truncated)' : content; - - await emitStatus(agentId, 'running', 'tool_browser_get_page_content', `Retrieved page ${format}`, { arguments: input }); - - return { text: `Page ${format.toUpperCase()} Content:\n${displayContent}` }; - }, - }); - - const browser_wait_for_page = tool({ - description: 'Wait for the page to finish loading or for a specific element to appear. Use this after navigation if you need to ensure content is fully rendered.', - inputSchema: zodSchema(waitForPageLoadSchema), - execute: async (input): Promise => { - const { selector, timeout_sec } = input; - await emitStatus(agentId, 'running', 'tool_browser_wait_for_page', selector ? `Waiting for ${selector}` : 'Waiting for page load', { arguments: input }); - - const session = browserSessions.get(agentId); - if (!session) { - return { text: 'Error: No browser session found. Call browser_create_session first.' }; - } - - const { sessionId, client } = session; - - try { - if (selector) { - await client.browsers.playwright.execute(sessionId, { - code: `await page.waitForSelector('${selector.replace(/'/g, "\\'")}', { timeout: ${(timeout_sec || 30) * 1000} });`, - timeout_sec: (timeout_sec || 30) + 5, - }); - return { text: `Element "${selector}" found and visible.` }; - } else { - await client.browsers.playwright.execute(sessionId, { - code: ` - await page.waitForLoadState('domcontentloaded', { timeout: ${(timeout_sec || 30) * 1000} }); - await page.waitForTimeout(1000); - try { - await page.waitForLoadState('networkidle', { timeout: 5000 }); - } catch (e) { - // Network may not be idle, that's okay - } - `, - timeout_sec: (timeout_sec || 30) + 10, - }); - return { text: 'Page finished loading.' }; - } - } catch (error) { - const message = error instanceof Error ? error.message : 'Unknown error'; - return { text: `Timeout waiting for page: ${message}` }; - } - }, - }); - return { - browser_start_dev_server, - browser_create_session, - browser_screenshot, - browser_execute, - browser_navigate, - browser_click, - browser_type, - browser_close_session, - browser_get_console_logs, - browser_get_network_logs, - browser_get_page_content, - browser_wait_for_page, + browser_start_dev_server: buildStartDevServerTool({ agentId, sandbox }), + browser_create_session: buildCreateSessionTool({ agentId }), + browser_screenshot: buildScreenshotTool({ agentId }), + browser_execute: buildExecuteTool({ agentId }), + browser_navigate: buildNavigateTool({ agentId }), + browser_click: buildClickTool({ agentId }), + browser_type: buildTypeTool({ agentId }), + browser_close_session: buildCloseSessionTool({ agentId }), + browser_get_console_logs: buildGetConsoleLogsTool({ agentId }), + browser_get_network_logs: buildGetNetworkLogsTool({ agentId }), + browser_get_page_content: buildGetPageContentTool({ agentId }), + browser_wait_for_page: buildWaitForPageTool({ agentId }), }; } -// Cleanup function to be called when agent workflow ends export async function cleanupBrowserSession(agentId: number): Promise { const session = browserSessions.get(agentId); if (session) { @@ -570,7 +44,6 @@ export async function cleanupBrowserSession(agentId: number): Promise { } browserSessions.delete(agentId); } - // Clean up log storage consoleLogs.delete(agentId); networkLogs.delete(agentId); } diff --git a/backend/src/tools/kernel/session.ts b/backend/src/tools/kernel/session.ts new file mode 100644 index 0000000..a711b79 --- /dev/null +++ b/backend/src/tools/kernel/session.ts @@ -0,0 +1,24 @@ +import Kernel from '@onkernel/sdk'; +import type { ToolCallImage } from '../../db/entities/ToolCall'; + +export interface BrowserSession { + sessionId: string; + client: Kernel; +} + +export type BrowserToolResult = { + text: string; + images?: ToolCallImage[]; +}; + +export const browserSessions: Map = new Map(); +export const consoleLogs: Map> = new Map(); +export const networkLogs: Map> = new Map(); + +export function getKernelClient(): Kernel { + const apiKey = process.env.KERNEL_API_KEY; + if (!apiKey) { + throw new Error('KERNEL_API_KEY environment variable is not set'); + } + return new Kernel({ apiKey }); +} diff --git a/backend/src/tools/kernel/tools/click.ts b/backend/src/tools/kernel/tools/click.ts new file mode 100644 index 0000000..cf7e5be --- /dev/null +++ b/backend/src/tools/kernel/tools/click.ts @@ -0,0 +1,37 @@ +import { z } from 'zod'; +import { tool, zodSchema } from 'ai'; +import { emitStatus } from '../../../stream/events'; +import { browserSessions, type BrowserToolResult } from '../session'; + +const clickSchema = z.object({ + selector: z.string().describe('CSS selector for the element to click'), +}); + +export function buildClickTool(params: { agentId: number }) { + const { agentId } = params; + + return tool({ + description: 'Click on an element in the browser using a CSS selector.', + inputSchema: zodSchema(clickSchema), + execute: async (input): Promise => { + const { selector } = input; + await emitStatus(agentId, 'running', 'tool_browser_click', `Clicking ${selector}`, { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + await client.browsers.playwright.execute(sessionId, { + code: `await page.click('${selector.replace(/'/g, "\\'")}');`, + timeout_sec: 30, + }); + + await emitStatus(agentId, 'running', 'tool_browser_click', `Clicked ${selector}`, { arguments: input }); + + return { text: `Successfully clicked on element: ${selector}` }; + }, + }); +} diff --git a/backend/src/tools/kernel/tools/closeSession.ts b/backend/src/tools/kernel/tools/closeSession.ts new file mode 100644 index 0000000..4f1d681 --- /dev/null +++ b/backend/src/tools/kernel/tools/closeSession.ts @@ -0,0 +1,34 @@ +import { z } from 'zod'; +import { tool, zodSchema } from 'ai'; +import { emitStatus } from '../../../stream/events'; +import { browserSessions, consoleLogs, networkLogs, type BrowserToolResult } from '../session'; + +const closeSessionSchema = z.object({}); + +export function buildCloseSessionTool(params: { agentId: number }) { + const { agentId } = params; + + return tool({ + description: 'Close the current browser session and clean up resources.', + inputSchema: zodSchema(closeSessionSchema), + execute: async (input): Promise => { + await emitStatus(agentId, 'running', 'tool_browser_close_session', 'Closing browser session', { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'No browser session to close.' }; + } + + const { sessionId, client } = session; + + await client.browsers.deleteByID(sessionId); + browserSessions.delete(agentId); + consoleLogs.delete(agentId); + networkLogs.delete(agentId); + + await emitStatus(agentId, 'running', 'tool_browser_close_session', 'Browser session closed', { arguments: input }); + + return { text: 'Browser session closed successfully.' }; + }, + }); +} diff --git a/backend/src/tools/kernel/tools/createSession.ts b/backend/src/tools/kernel/tools/createSession.ts new file mode 100644 index 0000000..0fb1d33 --- /dev/null +++ b/backend/src/tools/kernel/tools/createSession.ts @@ -0,0 +1,90 @@ +import { z } from 'zod'; +import { tool, zodSchema } from 'ai'; +import { emitStatus } from '../../../stream/events'; +import { browserSessions, consoleLogs, networkLogs, getKernelClient, type BrowserToolResult } from '../session'; + +const createSessionSchema = z.object({ + url: z.string().optional().describe('Optional initial URL to navigate to after creating the browser'), +}); + +export function buildCreateSessionTool(params: { agentId: number }) { + const { agentId } = params; + + return tool({ + description: + 'Create a new browser session using Kernel.sh. This starts a remote browser that can be controlled via other browser tools. Call browser_start_dev_server first if you need to access an app running in the sandbox.', + inputSchema: zodSchema(createSessionSchema), + execute: async (input): Promise => { + const { url } = input; + await emitStatus(agentId, 'running', 'tool_browser_create_session', 'Creating browser session', { arguments: input }); + + const client = getKernelClient(); + const browserResponse = await client.browsers.create({ + headless: false, + timeout_seconds: 300, + }); + + const sessionId = browserResponse.session_id; + + browserSessions.set(agentId, { sessionId, client }); + + consoleLogs.set(agentId, []); + networkLogs.set(agentId, []); + + await client.browsers.playwright.execute(sessionId, { + code: ` + // Store logs in page context for later retrieval + window.__consoleLogs = window.__consoleLogs || []; + window.__networkLogs = window.__networkLogs || []; + + // Capture console messages + const originalConsole = { log: console.log, warn: console.warn, error: console.error, info: console.info }; + ['log', 'warn', 'error', 'info'].forEach(type => { + console[type] = function(...args) { + window.__consoleLogs.push({ type, text: args.map(a => String(a)).join(' '), timestamp: new Date().toISOString() }); + originalConsole[type].apply(console, args); + }; + }); + + // Capture network requests via Performance API + const observer = new PerformanceObserver((list) => { + for (const entry of list.getEntries()) { + if (entry.entryType === 'resource') { + window.__networkLogs.push({ + method: 'GET', + url: entry.name, + status: 200, + timestamp: new Date().toISOString() + }); + } + } + }); + observer.observe({ entryTypes: ['resource'] }); + `, + timeout_sec: 10, + }); + + let result = `Browser session created. Session ID: ${sessionId}`; + if (browserResponse.browser_live_view_url) { + result += `\nLive view URL: ${browserResponse.browser_live_view_url}`; + } + result += `\nConsole and network logging enabled. Use browser_get_console_logs and browser_get_network_logs to retrieve logs.`; + + if (url) { + await client.browsers.playwright.execute(sessionId, { + code: `await page.goto('${url}', { waitUntil: 'domcontentloaded', timeout: 30000 });`, + timeout_sec: 35, + }); + await client.browsers.playwright.execute(sessionId, { + code: `await page.waitForTimeout(2000);`, + timeout_sec: 10, + }); + result += `\nNavigated to: ${url}`; + } + + await emitStatus(agentId, 'running', 'tool_browser_create_session', result, { arguments: input }); + + return { text: result }; + }, + }); +} diff --git a/backend/src/tools/kernel/tools/execute.ts b/backend/src/tools/kernel/tools/execute.ts new file mode 100644 index 0000000..cfd881a --- /dev/null +++ b/backend/src/tools/kernel/tools/execute.ts @@ -0,0 +1,41 @@ +import { z } from 'zod'; +import { tool, zodSchema } from 'ai'; +import { emitStatus } from '../../../stream/events'; +import { browserSessions, type BrowserToolResult } from '../session'; + +const executeSchema = z.object({ + code: z.string().describe('Playwright/JavaScript code to execute. Has access to `page`, `context`, and `browser` variables.'), + timeout_sec: z.number().optional().default(60).describe('Execution timeout in seconds'), +}); + +export function buildExecuteTool(params: { agentId: number }) { + const { agentId } = params; + + return tool({ + description: + 'Execute arbitrary Playwright code in the browser. Has access to `page`, `context`, and `browser` variables. Use this for complex interactions not covered by other tools.', + inputSchema: zodSchema(executeSchema), + execute: async (input): Promise => { + const { code, timeout_sec } = input; + await emitStatus(agentId, 'running', 'tool_browser_execute', `Executing Playwright code`, { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + const result = await client.browsers.playwright.execute(sessionId, { + code, + timeout_sec: timeout_sec || 60, + }); + + await emitStatus(agentId, 'running', 'tool_browser_execute', 'Code executed', { arguments: input }); + + return { + text: result.result !== undefined ? `Execution result: ${JSON.stringify(result.result)}` : 'Code executed successfully.', + }; + }, + }); +} diff --git a/backend/src/tools/kernel/tools/getConsoleLogs.ts b/backend/src/tools/kernel/tools/getConsoleLogs.ts new file mode 100644 index 0000000..3e0d0d5 --- /dev/null +++ b/backend/src/tools/kernel/tools/getConsoleLogs.ts @@ -0,0 +1,51 @@ +import { z } from 'zod'; +import { tool, zodSchema } from 'ai'; +import { emitStatus } from '../../../stream/events'; +import { browserSessions, type BrowserToolResult } from '../session'; + +const getConsoleLogsSchema = z.object({ + clear: z.boolean().optional().default(false).describe('Whether to clear the logs after retrieving them'), +}); + +export function buildGetConsoleLogsTool(params: { agentId: number }) { + const { agentId } = params; + + return tool({ + description: 'Get console logs (log, warn, error, info) captured from the browser. Useful for debugging JavaScript errors and application behavior.', + inputSchema: zodSchema(getConsoleLogsSchema), + execute: async (input): Promise => { + const { clear } = input; + await emitStatus(agentId, 'running', 'tool_browser_get_console_logs', 'Retrieving console logs', { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + const result = await client.browsers.playwright.execute(sessionId, { + code: ` + const logs = window.__consoleLogs || []; + if (${clear}) { + window.__consoleLogs = []; + } + return logs; + `, + timeout_sec: 10, + }); + + const logs = (result.result as Array<{ type: string; text: string; timestamp: string }>) || []; + + if (logs.length === 0) { + return { text: 'No console logs captured.' }; + } + + const formattedLogs = logs.map((log) => `[${log.timestamp}] [${log.type.toUpperCase()}] ${log.text}`).join('\n'); + + await emitStatus(agentId, 'running', 'tool_browser_get_console_logs', `Retrieved ${logs.length} console logs`, { arguments: input }); + + return { text: `Console Logs (${logs.length} entries):\n${formattedLogs}` }; + }, + }); +} diff --git a/backend/src/tools/kernel/tools/getNetworkLogs.ts b/backend/src/tools/kernel/tools/getNetworkLogs.ts new file mode 100644 index 0000000..a5f6384 --- /dev/null +++ b/backend/src/tools/kernel/tools/getNetworkLogs.ts @@ -0,0 +1,51 @@ +import { z } from 'zod'; +import { tool, zodSchema } from 'ai'; +import { emitStatus } from '../../../stream/events'; +import { browserSessions, type BrowserToolResult } from '../session'; + +const getNetworkLogsSchema = z.object({ + clear: z.boolean().optional().default(false).describe('Whether to clear the logs after retrieving them'), +}); + +export function buildGetNetworkLogsTool(params: { agentId: number }) { + const { agentId } = params; + + return tool({ + description: 'Get network request logs captured from the browser. Useful for debugging API calls, failed requests, and resource loading.', + inputSchema: zodSchema(getNetworkLogsSchema), + execute: async (input): Promise => { + const { clear } = input; + await emitStatus(agentId, 'running', 'tool_browser_get_network_logs', 'Retrieving network logs', { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + const result = await client.browsers.playwright.execute(sessionId, { + code: ` + const logs = window.__networkLogs || []; + if (${clear}) { + window.__networkLogs = []; + } + return logs; + `, + timeout_sec: 10, + }); + + const logs = (result.result as Array<{ method: string; url: string; status?: number; timestamp: string }>) || []; + + if (logs.length === 0) { + return { text: 'No network logs captured.' }; + } + + const formattedLogs = logs.map((log) => `[${log.timestamp}] ${log.method} ${log.url} ${log.status ? `(${log.status})` : ''}`).join('\n'); + + await emitStatus(agentId, 'running', 'tool_browser_get_network_logs', `Retrieved ${logs.length} network logs`, { arguments: input }); + + return { text: `Network Logs (${logs.length} entries):\n${formattedLogs}` }; + }, + }); +} diff --git a/backend/src/tools/kernel/tools/getPageContent.ts b/backend/src/tools/kernel/tools/getPageContent.ts new file mode 100644 index 0000000..598edda --- /dev/null +++ b/backend/src/tools/kernel/tools/getPageContent.ts @@ -0,0 +1,46 @@ +import { z } from 'zod'; +import { tool, zodSchema } from 'ai'; +import { emitStatus } from '../../../stream/events'; +import { browserSessions, type BrowserToolResult } from '../session'; + +const getPageContentSchema = z.object({ + format: z.enum(['html', 'text']).optional().default('text').describe('Format to return: "html" for full HTML, "text" for visible text only'), +}); + +export function buildGetPageContentTool(params: { agentId: number }) { + const { agentId } = params; + + return tool({ + description: + 'Get the current page content as HTML or visible text. Useful for understanding what the browser is displaying and debugging rendering issues.', + inputSchema: zodSchema(getPageContentSchema), + execute: async (input): Promise => { + const { format } = input; + await emitStatus(agentId, 'running', 'tool_browser_get_page_content', `Getting page content as ${format}`, { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + const code = format === 'html' ? `return await page.content();` : `return await page.innerText('body');`; + + const result = await client.browsers.playwright.execute(sessionId, { + code, + timeout_sec: 15, + }); + + const content = (result.result as string) || ''; + + const maxLength = 50000; + const truncated = content.length > maxLength; + const displayContent = truncated ? content.substring(0, maxLength) + '\n\n... (content truncated)' : content; + + await emitStatus(agentId, 'running', 'tool_browser_get_page_content', `Retrieved page ${format}`, { arguments: input }); + + return { text: `Page ${format.toUpperCase()} Content:\n${displayContent}` }; + }, + }); +} diff --git a/backend/src/tools/kernel/tools/navigate.ts b/backend/src/tools/kernel/tools/navigate.ts new file mode 100644 index 0000000..e0d3259 --- /dev/null +++ b/backend/src/tools/kernel/tools/navigate.ts @@ -0,0 +1,47 @@ +import { z } from 'zod'; +import { tool, zodSchema } from 'ai'; +import { emitStatus } from '../../../stream/events'; +import { browserSessions, type BrowserToolResult } from '../session'; + +const navigateSchema = z.object({ + url: z.string().describe('URL to navigate to'), +}); + +export function buildNavigateTool(params: { agentId: number }) { + const { agentId } = params; + + return tool({ + description: 'Navigate the browser to a specific URL. Waits for page to load.', + inputSchema: zodSchema(navigateSchema), + execute: async (input): Promise => { + const { url } = input; + await emitStatus(agentId, 'running', 'tool_browser_navigate', `Navigating to ${url}`, { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + await client.browsers.playwright.execute(sessionId, { + code: ` + await page.goto('${url}', { waitUntil: 'domcontentloaded', timeout: 30000 }); + // Wait for any pending JS to execute + await page.waitForTimeout(2000); + // Try to wait for network idle, but don't fail if it times out + try { + await page.waitForLoadState('networkidle', { timeout: 5000 }); + } catch (e) { + // Page may have continuous network activity, that's okay + } + `, + timeout_sec: 45, + }); + + await emitStatus(agentId, 'running', 'tool_browser_navigate', `Navigated to ${url}`, { arguments: input }); + + return { text: `Successfully navigated to ${url}` }; + }, + }); +} diff --git a/backend/src/tools/kernel/tools/screenshot.ts b/backend/src/tools/kernel/tools/screenshot.ts new file mode 100644 index 0000000..ea511fc --- /dev/null +++ b/backend/src/tools/kernel/tools/screenshot.ts @@ -0,0 +1,43 @@ +import { z } from 'zod'; +import { tool, zodSchema } from 'ai'; +import { emitStatus } from '../../../stream/events'; +import type { ToolCallImage } from '../../../db/entities/ToolCall'; +import { browserSessions, type BrowserToolResult } from '../session'; + +const screenshotSchema = z.object({}); + +export function buildScreenshotTool(params: { agentId: number }) { + const { agentId } = params; + + return tool({ + description: 'Capture a screenshot of the current browser page. The screenshot will be stored and can be viewed in the tool call history.', + inputSchema: zodSchema(screenshotSchema), + execute: async (input): Promise => { + await emitStatus(agentId, 'running', 'tool_browser_screenshot', 'Capturing screenshot', { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + const response = await client.browsers.computer.captureScreenshot(sessionId); + const blob = await response.blob(); + const arrayBuffer = await blob.arrayBuffer(); + const base64 = Buffer.from(arrayBuffer).toString('base64'); + + const image: ToolCallImage = { + data: base64, + mimeType: 'image/png', + }; + + await emitStatus(agentId, 'running', 'tool_browser_screenshot', 'Screenshot captured', { arguments: input }); + + return { + text: 'Screenshot captured successfully.', + images: [image], + }; + }, + }); +} diff --git a/backend/src/tools/kernel/tools/startDevServer.ts b/backend/src/tools/kernel/tools/startDevServer.ts new file mode 100644 index 0000000..d5e8d5b --- /dev/null +++ b/backend/src/tools/kernel/tools/startDevServer.ts @@ -0,0 +1,64 @@ +import { z } from 'zod'; +import { tool, zodSchema } from 'ai'; +import type { Sandbox } from '@vercel/sandbox'; +import { emitStatus } from '../../../stream/events'; +import type { BrowserToolResult } from '../session'; + +const startDevServerSchema = z.object({ + command: z.string().describe('Command to start the dev server (e.g., "npm run dev", "bun dev")'), + port: z.number().describe('Port the dev server will run on (e.g., 3000)'), +}); + +export function buildStartDevServerTool(params: { agentId: number; sandbox: Sandbox }) { + const { agentId, sandbox } = params; + + return tool({ + description: + 'Start a development server in the sandbox and expose it via a public URL. Use this before browser_create_session to make your app accessible to the browser.', + inputSchema: zodSchema(startDevServerSchema), + execute: async (input): Promise => { + const { command, port } = input; + await emitStatus(agentId, 'running', 'tool_browser_start_dev_server', `Starting dev server: ${command}`, { arguments: input }); + + await sandbox.runCommand({ + cmd: 'bash', + args: ['-c', command], + detached: true, + }); + + const publicUrl = sandbox.domain(port); + + const maxAttempts = 30; + let serverReady = false; + for (let attempt = 0; attempt < maxAttempts; attempt++) { + await new Promise((resolve) => setTimeout(resolve, 2000)); + try { + const response = await fetch(publicUrl, { method: 'HEAD', signal: AbortSignal.timeout(5000) }); + if (response.ok || response.status < 500) { + serverReady = true; + break; + } + } catch { + // Server not ready yet, continue polling + } + if (attempt % 5 === 0) { + await emitStatus(agentId, 'running', 'tool_browser_start_dev_server', `Waiting for server to start... (${(attempt + 1) * 2}s)`, { + arguments: input, + }); + } + } + + if (!serverReady) { + return { + text: `Dev server started but may not be ready yet. Public URL: ${publicUrl}\nNote: The server did not respond within 60 seconds. It may still be starting up or there could be an issue with the application.`, + }; + } + + await emitStatus(agentId, 'running', 'tool_browser_start_dev_server', `Dev server started at ${publicUrl}`, { arguments: input }); + + return { + text: `Dev server started successfully and is responding. Public URL: ${publicUrl}`, + }; + }, + }); +} diff --git a/backend/src/tools/kernel/tools/type.ts b/backend/src/tools/kernel/tools/type.ts new file mode 100644 index 0000000..b2ad886 --- /dev/null +++ b/backend/src/tools/kernel/tools/type.ts @@ -0,0 +1,38 @@ +import { z } from 'zod'; +import { tool, zodSchema } from 'ai'; +import { emitStatus } from '../../../stream/events'; +import { browserSessions, type BrowserToolResult } from '../session'; + +const typeSchema = z.object({ + selector: z.string().describe('CSS selector for the input element'), + text: z.string().describe('Text to type into the element'), +}); + +export function buildTypeTool(params: { agentId: number }) { + const { agentId } = params; + + return tool({ + description: 'Type text into an input element in the browser.', + inputSchema: zodSchema(typeSchema), + execute: async (input): Promise => { + const { selector, text } = input; + await emitStatus(agentId, 'running', 'tool_browser_type', `Typing into ${selector}`, { arguments: input }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + await client.browsers.playwright.execute(sessionId, { + code: `await page.fill('${selector.replace(/'/g, "\\'")}', '${text.replace(/'/g, "\\'")}');`, + timeout_sec: 30, + }); + + await emitStatus(agentId, 'running', 'tool_browser_type', `Typed into ${selector}`, { arguments: input }); + + return { text: `Successfully typed "${text}" into element: ${selector}` }; + }, + }); +} diff --git a/backend/src/tools/kernel/tools/waitForPage.ts b/backend/src/tools/kernel/tools/waitForPage.ts new file mode 100644 index 0000000..a449848 --- /dev/null +++ b/backend/src/tools/kernel/tools/waitForPage.ts @@ -0,0 +1,59 @@ +import { z } from 'zod'; +import { tool, zodSchema } from 'ai'; +import { emitStatus } from '../../../stream/events'; +import { browserSessions, type BrowserToolResult } from '../session'; + +const waitForPageLoadSchema = z.object({ + selector: z.string().optional().describe('Optional CSS selector to wait for'), + timeout_sec: z.number().optional().default(30).describe('Timeout in seconds'), +}); + +export function buildWaitForPageTool(params: { agentId: number }) { + const { agentId } = params; + + return tool({ + description: + 'Wait for the page to finish loading or for a specific element to appear. Use this after navigation if you need to ensure content is fully rendered.', + inputSchema: zodSchema(waitForPageLoadSchema), + execute: async (input): Promise => { + const { selector, timeout_sec } = input; + await emitStatus(agentId, 'running', 'tool_browser_wait_for_page', selector ? `Waiting for ${selector}` : 'Waiting for page load', { + arguments: input, + }); + + const session = browserSessions.get(agentId); + if (!session) { + return { text: 'Error: No browser session found. Call browser_create_session first.' }; + } + + const { sessionId, client } = session; + + try { + if (selector) { + await client.browsers.playwright.execute(sessionId, { + code: `await page.waitForSelector('${selector.replace(/'/g, "\\'")}', { timeout: ${(timeout_sec || 30) * 1000} });`, + timeout_sec: (timeout_sec || 30) + 5, + }); + return { text: `Element "${selector}" found and visible.` }; + } else { + await client.browsers.playwright.execute(sessionId, { + code: ` + await page.waitForLoadState('domcontentloaded', { timeout: ${(timeout_sec || 30) * 1000} }); + await page.waitForTimeout(1000); + try { + await page.waitForLoadState('networkidle', { timeout: 5000 }); + } catch (e) { + // Network may not be idle, that's okay + } + `, + timeout_sec: (timeout_sec || 30) + 10, + }); + return { text: 'Page finished loading.' }; + } + } catch (error) { + const message = error instanceof Error ? error.message : 'Unknown error'; + return { text: `Timeout waiting for page: ${message}` }; + } + }, + }); +} diff --git a/backend/src/workflows/helpers/sandbox.ts b/backend/src/workflows/helpers/sandbox.ts index 855e400..b9d1e95 100644 --- a/backend/src/workflows/helpers/sandbox.ts +++ b/backend/src/workflows/helpers/sandbox.ts @@ -6,13 +6,7 @@ import { updateAgent } from './agents'; // Common ports for dev servers (Vercel Sandbox allows up to 4 ports) export const DEFAULT_BROWSER_PORTS = [3000, 3001, 5173]; -export async function createSandbox( - agent: Agent, - token: string, - repositoryFullName: string, - baseBranch: string, - ports?: number[] -): Promise { +export async function createSandbox(agent: Agent, token: string, repositoryFullName: string, baseBranch: string, ports?: number[]): Promise { const sandbox = await Sandbox.create({ token: process.env.VERCEL_TOKEN, teamId: process.env.VERCEL_TEAM_ID, diff --git a/backend/src/workflows/steps.ts b/backend/src/workflows/steps.ts index 9d2cfc5..60edc7f 100644 --- a/backend/src/workflows/steps.ts +++ b/backend/src/workflows/steps.ts @@ -35,13 +35,7 @@ export async function validateAndGetToken(agent: Agent, repositoryFullName: stri return { repositoryFullName: repoName, token }; } -export async function prepareSandbox( - agent: Agent, - token: string, - repositoryFullName: string, - baseBranch: string, - toolSlugs?: string[] -) { +export async function prepareSandbox(agent: Agent, token: string, repositoryFullName: string, baseBranch: string, toolSlugs?: string[]) { await emitStatus(agent.id, 'starting', 'agent_init', 'preparing sandbox'); // Expose ports if browser tools are enabled From 322134aef44f0b1720d0d7afc3b484819b876fb4 Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Wed, 14 Jan 2026 19:18:50 -0600 Subject: [PATCH 03/14] fix prompting/zod params --- backend/src/tools/kernel/tools/createSession.ts | 2 +- backend/src/tools/kernel/tools/startDevServer.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/tools/kernel/tools/createSession.ts b/backend/src/tools/kernel/tools/createSession.ts index 0fb1d33..5a00e17 100644 --- a/backend/src/tools/kernel/tools/createSession.ts +++ b/backend/src/tools/kernel/tools/createSession.ts @@ -4,7 +4,7 @@ import { emitStatus } from '../../../stream/events'; import { browserSessions, consoleLogs, networkLogs, getKernelClient, type BrowserToolResult } from '../session'; const createSessionSchema = z.object({ - url: z.string().optional().describe('Optional initial URL to navigate to after creating the browser'), + url: z.string().describe('Initial URL to navigate to after creating the browser'), }); export function buildCreateSessionTool(params: { agentId: number }) { diff --git a/backend/src/tools/kernel/tools/startDevServer.ts b/backend/src/tools/kernel/tools/startDevServer.ts index d5e8d5b..cdf1878 100644 --- a/backend/src/tools/kernel/tools/startDevServer.ts +++ b/backend/src/tools/kernel/tools/startDevServer.ts @@ -14,7 +14,7 @@ export function buildStartDevServerTool(params: { agentId: number; sandbox: Sand return tool({ description: - 'Start a development server in the sandbox and expose it via a public URL. Use this before browser_create_session to make your app accessible to the browser.', + 'Start a development server in the sandbox and expose it via a public URL. Use this before browser_create_session to make your app accessible to the browser. Ensure you also install dependencies, as this is a fresh sandbox and is missing them.', inputSchema: zodSchema(startDevServerSchema), execute: async (input): Promise => { const { command, port } = input; From 77e3676a16c221c9e453317b26256280128ac517 Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Thu, 15 Jan 2026 02:45:10 -0600 Subject: [PATCH 04/14] add image to tool container --- .../pages/Workspace/ToolsContainer.module.css | 54 +++++++++++++++++++ .../src/pages/Workspace/ToolsContainer.tsx | 34 ++++++++++++ 2 files changed, 88 insertions(+) diff --git a/frontend/src/pages/Workspace/ToolsContainer.module.css b/frontend/src/pages/Workspace/ToolsContainer.module.css index 739d35b..8517218 100644 --- a/frontend/src/pages/Workspace/ToolsContainer.module.css +++ b/frontend/src/pages/Workspace/ToolsContainer.module.css @@ -157,3 +157,57 @@ overflow-y: auto; line-height: 1.5; } + +.screenshotContainer { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: 8px; +} + +.screenshotImage { + max-width: 120px; + max-height: 80px; + border-radius: 6px; + border: 1px solid rgba(255, 255, 255, 0.1); + cursor: pointer; + transition: transform 0.15s ease, border-color 0.15s ease; + object-fit: contain; + background: rgba(0, 0, 0, 0.3); +} + +.screenshotImage:hover { + transform: scale(1.02); + border-color: rgba(255, 255, 255, 0.25); +} + +.imageOverlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.85); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + cursor: pointer; + backdrop-filter: blur(4px); +} + +.imageOverlayContent { + max-width: 90vw; + max-height: 90vh; + display: flex; + align-items: center; + justify-content: center; +} + +.screenshotImageFull { + max-width: 100%; + max-height: 90vh; + border-radius: 8px; + border: 1px solid rgba(255, 255, 255, 0.15); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5); +} diff --git a/frontend/src/pages/Workspace/ToolsContainer.tsx b/frontend/src/pages/Workspace/ToolsContainer.tsx index b4592c1..d531b79 100644 --- a/frontend/src/pages/Workspace/ToolsContainer.tsx +++ b/frontend/src/pages/Workspace/ToolsContainer.tsx @@ -1,6 +1,33 @@ import type { ToolCall } from '../../lib/types'; import style from './ToolsContainer.module.css'; import { BsChevronDown, BsX } from 'react-icons/bs'; +import { useState } from 'react'; + +function ScreenshotImage({ data, mimeType }: { data: string; mimeType: string }) { + const [isExpanded, setIsExpanded] = useState(false); + + return ( + <> + Screenshot setIsExpanded(true)} + /> + {isExpanded && ( +
setIsExpanded(false)}> +
+ Screenshot (full size) +
+
+ )} + + ); +} export default function ToolsContainer({ toolCalls, @@ -61,6 +88,13 @@ export default function ToolsContainer({ {typeof toolCall.result === 'object' ? JSON.stringify(toolCall.result, null, 2) : toolCall.result} )} + {toolCall.images && toolCall.images.length > 0 && ( +
+ {toolCall.images.map((image, index) => ( + + ))} +
+ )} ))} From 59c9732295ef05f5b6ae8f4db1ae8de028fac20d Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Thu, 15 Jan 2026 04:40:46 -0600 Subject: [PATCH 05/14] fix vuln --- backend/src/tools/kernel/tools/click.ts | 2 +- backend/src/tools/kernel/tools/createSession.ts | 2 +- backend/src/tools/kernel/tools/navigate.ts | 2 +- backend/src/tools/kernel/tools/type.ts | 2 +- backend/src/tools/kernel/tools/waitForPage.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/tools/kernel/tools/click.ts b/backend/src/tools/kernel/tools/click.ts index cf7e5be..7c0e73b 100644 --- a/backend/src/tools/kernel/tools/click.ts +++ b/backend/src/tools/kernel/tools/click.ts @@ -25,7 +25,7 @@ export function buildClickTool(params: { agentId: number }) { const { sessionId, client } = session; await client.browsers.playwright.execute(sessionId, { - code: `await page.click('${selector.replace(/'/g, "\\'")}');`, + code: `await page.click(${JSON.stringify(selector)});`, timeout_sec: 30, }); diff --git a/backend/src/tools/kernel/tools/createSession.ts b/backend/src/tools/kernel/tools/createSession.ts index 5a00e17..5c90e8c 100644 --- a/backend/src/tools/kernel/tools/createSession.ts +++ b/backend/src/tools/kernel/tools/createSession.ts @@ -72,7 +72,7 @@ export function buildCreateSessionTool(params: { agentId: number }) { if (url) { await client.browsers.playwright.execute(sessionId, { - code: `await page.goto('${url}', { waitUntil: 'domcontentloaded', timeout: 30000 });`, + code: `await page.goto(${JSON.stringify(url)}, { waitUntil: 'domcontentloaded', timeout: 30000 });`, timeout_sec: 35, }); await client.browsers.playwright.execute(sessionId, { diff --git a/backend/src/tools/kernel/tools/navigate.ts b/backend/src/tools/kernel/tools/navigate.ts index e0d3259..8e71406 100644 --- a/backend/src/tools/kernel/tools/navigate.ts +++ b/backend/src/tools/kernel/tools/navigate.ts @@ -26,7 +26,7 @@ export function buildNavigateTool(params: { agentId: number }) { await client.browsers.playwright.execute(sessionId, { code: ` - await page.goto('${url}', { waitUntil: 'domcontentloaded', timeout: 30000 }); + await page.goto(${JSON.stringify(url)}, { waitUntil: 'domcontentloaded', timeout: 30000 }); // Wait for any pending JS to execute await page.waitForTimeout(2000); // Try to wait for network idle, but don't fail if it times out diff --git a/backend/src/tools/kernel/tools/type.ts b/backend/src/tools/kernel/tools/type.ts index b2ad886..162752c 100644 --- a/backend/src/tools/kernel/tools/type.ts +++ b/backend/src/tools/kernel/tools/type.ts @@ -26,7 +26,7 @@ export function buildTypeTool(params: { agentId: number }) { const { sessionId, client } = session; await client.browsers.playwright.execute(sessionId, { - code: `await page.fill('${selector.replace(/'/g, "\\'")}', '${text.replace(/'/g, "\\'")}');`, + code: `await page.fill(${JSON.stringify(selector)}, ${JSON.stringify(text)});`, timeout_sec: 30, }); diff --git a/backend/src/tools/kernel/tools/waitForPage.ts b/backend/src/tools/kernel/tools/waitForPage.ts index a449848..a0b9e7f 100644 --- a/backend/src/tools/kernel/tools/waitForPage.ts +++ b/backend/src/tools/kernel/tools/waitForPage.ts @@ -31,7 +31,7 @@ export function buildWaitForPageTool(params: { agentId: number }) { try { if (selector) { await client.browsers.playwright.execute(sessionId, { - code: `await page.waitForSelector('${selector.replace(/'/g, "\\'")}', { timeout: ${(timeout_sec || 30) * 1000} });`, + code: `await page.waitForSelector(${JSON.stringify(selector)}, { timeout: ${(timeout_sec || 30) * 1000} });`, timeout_sec: (timeout_sec || 30) + 5, }); return { text: `Element "${selector}" found and visible.` }; From 132c8d92a18b2beeefc2cf9f020b028e60c5e3c3 Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Thu, 15 Jan 2026 04:41:59 -0600 Subject: [PATCH 06/14] change screenshot config --- backend/src/tools/kernel/tools/screenshot.ts | 51 +++++++++++++++----- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/backend/src/tools/kernel/tools/screenshot.ts b/backend/src/tools/kernel/tools/screenshot.ts index ea511fc..bb05012 100644 --- a/backend/src/tools/kernel/tools/screenshot.ts +++ b/backend/src/tools/kernel/tools/screenshot.ts @@ -1,19 +1,17 @@ import { z } from 'zod'; -import { tool, zodSchema } from 'ai'; +import { tool } from 'ai'; import { emitStatus } from '../../../stream/events'; import type { ToolCallImage } from '../../../db/entities/ToolCall'; import { browserSessions, type BrowserToolResult } from '../session'; -const screenshotSchema = z.object({}); - export function buildScreenshotTool(params: { agentId: number }) { const { agentId } = params; - return tool({ - description: 'Capture a screenshot of the current browser page. The screenshot will be stored and can be viewed in the tool call history.', - inputSchema: zodSchema(screenshotSchema), - execute: async (input): Promise => { - await emitStatus(agentId, 'running', 'tool_browser_screenshot', 'Capturing screenshot', { arguments: input }); + return tool, BrowserToolResult>({ + description: 'Capture a screenshot of the current browser page. The screenshot will be returned as an image that you can see and analyze.', + inputSchema: z.object({}), + execute: async (_input, _options) => { + await emitStatus(agentId, 'running', 'tool_browser_screenshot', 'Capturing screenshot', { arguments: {} }); const session = browserSessions.get(agentId); if (!session) { @@ -22,22 +20,49 @@ export function buildScreenshotTool(params: { agentId: number }) { const { sessionId, client } = session; - const response = await client.browsers.computer.captureScreenshot(sessionId); - const blob = await response.blob(); - const arrayBuffer = await blob.arrayBuffer(); - const base64 = Buffer.from(arrayBuffer).toString('base64'); + const result = await client.browsers.playwright.execute(sessionId, { + code: ` + const screenshot = await page.screenshot({ + type: 'png', + fullPage: true, + }); + return screenshot.toString('base64'); + `, + timeout_sec: 60, + }); + const base64 = result.result as string; const image: ToolCallImage = { data: base64, mimeType: 'image/png', }; - await emitStatus(agentId, 'running', 'tool_browser_screenshot', 'Screenshot captured', { arguments: input }); + await emitStatus(agentId, 'running', 'tool_browser_screenshot', 'Screenshot captured', { arguments: {} }); return { text: 'Screenshot captured successfully.', images: [image], }; }, + toModelOutput: ({ output }) => { + const content: Array<{ type: 'text'; text: string } | { type: 'image-data'; data: string; mediaType: string }> = [ + { type: 'text' as const, text: output.text }, + ]; + + if (output.images && output.images.length > 0) { + for (const image of output.images) { + content.push({ + type: 'image-data' as const, + data: image.data, + mediaType: image.mimeType, + }); + } + } + + return { + type: 'content' as const, + value: content, + }; + }, }); } From 2a608e9f6ac43b3d12bb0f3f3269864e1377f1b1 Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Thu, 15 Jan 2026 05:12:51 -0600 Subject: [PATCH 07/14] remove unnecessary kernel.sh tools, rename grep tool to general command tool, store sandbox urls --- backend/src/tools/dynamic.ts | 9 ++- backend/src/tools/kernel/index.ts | 16 ++--- .../src/tools/kernel/tools/closeSession.ts | 34 ---------- .../src/tools/kernel/tools/createSession.ts | 22 +++++-- .../src/tools/kernel/tools/startDevServer.ts | 64 ------------------- backend/src/tools/sandboxTools.ts | 18 ++++-- backend/src/workflows/llm.ts | 4 +- backend/src/workflows/prompts.ts | 12 +++- 8 files changed, 57 insertions(+), 122 deletions(-) delete mode 100644 backend/src/tools/kernel/tools/closeSession.ts delete mode 100644 backend/src/tools/kernel/tools/startDevServer.ts diff --git a/backend/src/tools/dynamic.ts b/backend/src/tools/dynamic.ts index 397d8ad..fe73125 100644 --- a/backend/src/tools/dynamic.ts +++ b/backend/src/tools/dynamic.ts @@ -1,7 +1,8 @@ import type { Sandbox } from '@vercel/sandbox'; import { buildQueryRunnerTools, buildInsightTools, buildErrorTools, buildDocumentationTools, type ToolCollection } from './posthog/index'; import { buildCommitTools } from './github/commits'; -import { buildBrowserTools } from './kernel/index'; +import { buildBrowserTools, type SandboxUrl } from './kernel/index'; +import { DEFAULT_BROWSER_PORTS } from '../workflows/helpers/sandbox'; export async function buildDynamicTools(agentId: number, toolSlugs: string[], sandbox: Sandbox): Promise { const tools: ToolCollection = {}; @@ -34,7 +35,11 @@ export async function buildDynamicTools(agentId: number, toolSlugs: string[], sa } if (toolSlugs.includes('kernel/browser')) { - const browserTools = buildBrowserTools({ agentId, sandbox }); + const sandboxUrls: SandboxUrl[] = DEFAULT_BROWSER_PORTS.map((port) => ({ + port, + url: sandbox.domain(port), + })); + const browserTools = buildBrowserTools({ agentId, sandboxUrls }); Object.assign(tools, browserTools); } diff --git a/backend/src/tools/kernel/index.ts b/backend/src/tools/kernel/index.ts index 2957f29..846a9d2 100644 --- a/backend/src/tools/kernel/index.ts +++ b/backend/src/tools/kernel/index.ts @@ -1,13 +1,10 @@ -import type { Sandbox } from '@vercel/sandbox'; import { browserSessions, consoleLogs, networkLogs } from './session'; -import { buildStartDevServerTool } from './tools/startDevServer'; import { buildCreateSessionTool } from './tools/createSession'; import { buildScreenshotTool } from './tools/screenshot'; import { buildExecuteTool } from './tools/execute'; import { buildNavigateTool } from './tools/navigate'; import { buildClickTool } from './tools/click'; import { buildTypeTool } from './tools/type'; -import { buildCloseSessionTool } from './tools/closeSession'; import { buildGetConsoleLogsTool } from './tools/getConsoleLogs'; import { buildGetNetworkLogsTool } from './tools/getNetworkLogs'; import { buildGetPageContentTool } from './tools/getPageContent'; @@ -15,18 +12,21 @@ import { buildWaitForPageTool } from './tools/waitForPage'; export type { BrowserToolResult } from './session'; -export function buildBrowserTools(params: { agentId: number; sandbox: Sandbox }) { - const { agentId, sandbox } = params; +export interface SandboxUrl { + port: number; + url: string; +} + +export function buildBrowserTools(params: { agentId: number; sandboxUrls?: SandboxUrl[] }) { + const { agentId, sandboxUrls } = params; return { - browser_start_dev_server: buildStartDevServerTool({ agentId, sandbox }), - browser_create_session: buildCreateSessionTool({ agentId }), + browser_create_session: buildCreateSessionTool({ agentId, sandboxUrls }), browser_screenshot: buildScreenshotTool({ agentId }), browser_execute: buildExecuteTool({ agentId }), browser_navigate: buildNavigateTool({ agentId }), browser_click: buildClickTool({ agentId }), browser_type: buildTypeTool({ agentId }), - browser_close_session: buildCloseSessionTool({ agentId }), browser_get_console_logs: buildGetConsoleLogsTool({ agentId }), browser_get_network_logs: buildGetNetworkLogsTool({ agentId }), browser_get_page_content: buildGetPageContentTool({ agentId }), diff --git a/backend/src/tools/kernel/tools/closeSession.ts b/backend/src/tools/kernel/tools/closeSession.ts deleted file mode 100644 index 4f1d681..0000000 --- a/backend/src/tools/kernel/tools/closeSession.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { z } from 'zod'; -import { tool, zodSchema } from 'ai'; -import { emitStatus } from '../../../stream/events'; -import { browserSessions, consoleLogs, networkLogs, type BrowserToolResult } from '../session'; - -const closeSessionSchema = z.object({}); - -export function buildCloseSessionTool(params: { agentId: number }) { - const { agentId } = params; - - return tool({ - description: 'Close the current browser session and clean up resources.', - inputSchema: zodSchema(closeSessionSchema), - execute: async (input): Promise => { - await emitStatus(agentId, 'running', 'tool_browser_close_session', 'Closing browser session', { arguments: input }); - - const session = browserSessions.get(agentId); - if (!session) { - return { text: 'No browser session to close.' }; - } - - const { sessionId, client } = session; - - await client.browsers.deleteByID(sessionId); - browserSessions.delete(agentId); - consoleLogs.delete(agentId); - networkLogs.delete(agentId); - - await emitStatus(agentId, 'running', 'tool_browser_close_session', 'Browser session closed', { arguments: input }); - - return { text: 'Browser session closed successfully.' }; - }, - }); -} diff --git a/backend/src/tools/kernel/tools/createSession.ts b/backend/src/tools/kernel/tools/createSession.ts index 5c90e8c..616e299 100644 --- a/backend/src/tools/kernel/tools/createSession.ts +++ b/backend/src/tools/kernel/tools/createSession.ts @@ -2,17 +2,31 @@ import { z } from 'zod'; import { tool, zodSchema } from 'ai'; import { emitStatus } from '../../../stream/events'; import { browserSessions, consoleLogs, networkLogs, getKernelClient, type BrowserToolResult } from '../session'; +import type { SandboxUrl } from '../index'; const createSessionSchema = z.object({ url: z.string().describe('Initial URL to navigate to after creating the browser'), }); -export function buildCreateSessionTool(params: { agentId: number }) { - const { agentId } = params; +function buildDescription(sandboxUrls?: SandboxUrl[]): string { + let description = + 'Create a new browser session using Kernel.sh. This starts a remote browser that can be controlled via other browser tools. If you need to access an app running in the sandbox, first start the dev server using runCommand (e.g., "npm run dev &> devserver.log & sleep 2; tail devserver.log") before creating the session.'; + + if (sandboxUrls && sandboxUrls.length > 0) { + description += '\n\nIMPORTANT: The browser runs on an external service and CANNOT access localhost/127.0.0.1. Use these sandbox public URLs instead:'; + for (const { port, url } of sandboxUrls) { + description += `\n- Port ${port}: ${url}`; + } + } + + return description; +} + +export function buildCreateSessionTool(params: { agentId: number; sandboxUrls?: SandboxUrl[] }) { + const { agentId, sandboxUrls } = params; return tool({ - description: - 'Create a new browser session using Kernel.sh. This starts a remote browser that can be controlled via other browser tools. Call browser_start_dev_server first if you need to access an app running in the sandbox.', + description: buildDescription(sandboxUrls), inputSchema: zodSchema(createSessionSchema), execute: async (input): Promise => { const { url } = input; diff --git a/backend/src/tools/kernel/tools/startDevServer.ts b/backend/src/tools/kernel/tools/startDevServer.ts deleted file mode 100644 index cdf1878..0000000 --- a/backend/src/tools/kernel/tools/startDevServer.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { z } from 'zod'; -import { tool, zodSchema } from 'ai'; -import type { Sandbox } from '@vercel/sandbox'; -import { emitStatus } from '../../../stream/events'; -import type { BrowserToolResult } from '../session'; - -const startDevServerSchema = z.object({ - command: z.string().describe('Command to start the dev server (e.g., "npm run dev", "bun dev")'), - port: z.number().describe('Port the dev server will run on (e.g., 3000)'), -}); - -export function buildStartDevServerTool(params: { agentId: number; sandbox: Sandbox }) { - const { agentId, sandbox } = params; - - return tool({ - description: - 'Start a development server in the sandbox and expose it via a public URL. Use this before browser_create_session to make your app accessible to the browser. Ensure you also install dependencies, as this is a fresh sandbox and is missing them.', - inputSchema: zodSchema(startDevServerSchema), - execute: async (input): Promise => { - const { command, port } = input; - await emitStatus(agentId, 'running', 'tool_browser_start_dev_server', `Starting dev server: ${command}`, { arguments: input }); - - await sandbox.runCommand({ - cmd: 'bash', - args: ['-c', command], - detached: true, - }); - - const publicUrl = sandbox.domain(port); - - const maxAttempts = 30; - let serverReady = false; - for (let attempt = 0; attempt < maxAttempts; attempt++) { - await new Promise((resolve) => setTimeout(resolve, 2000)); - try { - const response = await fetch(publicUrl, { method: 'HEAD', signal: AbortSignal.timeout(5000) }); - if (response.ok || response.status < 500) { - serverReady = true; - break; - } - } catch { - // Server not ready yet, continue polling - } - if (attempt % 5 === 0) { - await emitStatus(agentId, 'running', 'tool_browser_start_dev_server', `Waiting for server to start... (${(attempt + 1) * 2}s)`, { - arguments: input, - }); - } - } - - if (!serverReady) { - return { - text: `Dev server started but may not be ready yet. Public URL: ${publicUrl}\nNote: The server did not respond within 60 seconds. It may still be starting up or there could be an issue with the application.`, - }; - } - - await emitStatus(agentId, 'running', 'tool_browser_start_dev_server', `Dev server started at ${publicUrl}`, { arguments: input }); - - return { - text: `Dev server started successfully and is responding. Public URL: ${publicUrl}`, - }; - }, - }); -} diff --git a/backend/src/tools/sandboxTools.ts b/backend/src/tools/sandboxTools.ts index c805148..561c149 100644 --- a/backend/src/tools/sandboxTools.ts +++ b/backend/src/tools/sandboxTools.ts @@ -25,8 +25,12 @@ export function sandboxTools(agentId: number, sandbox: Sandbox) { content: z.string().describe('New file contents'), }); - const grepInputSchema = z.object({ - command: z.string().describe('Shell command to run (e.g., `grep -R foo .`)'), + const runCommandInputSchema = z.object({ + command: z + .string() + .describe( + 'Shell command to run. For dev servers, use: "npm run dev &> devserver.log & sleep 2; tail devserver.log" to run in background and verify startup.' + ), }); const listFiles = tool({ @@ -66,19 +70,19 @@ export function sandboxTools(agentId: number, sandbox: Sandbox) { }, }); - const grep = tool({ - description: 'Run grep in the repository', - inputSchema: zodSchema(grepInputSchema), + const runCommand = tool({ + description: 'Run a shell command in the sandbox', + inputSchema: zodSchema(runCommandInputSchema), execute: async (input) => { const { command } = input; const result = await sandbox.runCommand({ cmd: 'bash', args: ['-c', command], }); - await emitStatus(agentId, 'running', 'tool_grep', await result.stdout(), { arguments: input }); + await emitStatus(agentId, 'running', 'tool_run_command', await result.stdout(), { arguments: input }); return result.stdout(); }, }); - return { listFiles, readFile, updateFile, grep }; + return { listFiles, readFile, updateFile, runCommand }; } diff --git a/backend/src/workflows/llm.ts b/backend/src/workflows/llm.ts index 1da4b62..378e3a6 100644 --- a/backend/src/workflows/llm.ts +++ b/backend/src/workflows/llm.ts @@ -49,8 +49,8 @@ export async function runAgentLLM( model, providerOptions: { openai: { - reasoningEffort: 'medium', - reasoningSummary: 'concise', + reasoningEffort: 'high', + reasoningSummary: 'detailed', }, }, system: AGENT_SYSTEM_PROMPT, diff --git a/backend/src/workflows/prompts.ts b/backend/src/workflows/prompts.ts index f466425..36efc05 100644 --- a/backend/src/workflows/prompts.ts +++ b/backend/src/workflows/prompts.ts @@ -1,7 +1,17 @@ export const AGENT_SYSTEM_PROMPT = ` You are Codee, an asynchronous coding agent. You work on GitHub repositories, read code, make changes, and explain your steps succinctly. -If the user requests git operations, prefer using tools (update_file, list_files, read_file, grep). +If the user requests git operations, prefer using tools (updateFile, listFiles, readFile, runCommand). Avoid destructive operations. Return concise reasoning and resulting changes. + +You are currently running in a FRESH sandbox. Before you were called, a fresh Node sandbox was created, and the repository was pulled from GitHub. +Ensure while calling tools, you do ANY required setup. Do not assume things like node_module folders are included. + +When using browser tools to test or interact with a web application: +1. Install dependencies first using runCommand (e.g., "npm install" or "bun install") +2. Start the dev server in background with logging to verify it starts correctly: + runCommand: "npm run dev &> devserver.log & sleep 2; tail devserver.log" + This redirects output to a log file, runs in background, waits, then shows the log to confirm startup. +3. Use the sandbox's public URLs (provided in the browser_create_session tool description) - NOT localhost/127.0.0.1 `; export const ORCHESTRATOR_AGENT_SYSTEM_PROMPT = ` From cea1c0bde49699987d50de6a9a776f1c87a098a3 Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Thu, 15 Jan 2026 05:30:14 -0600 Subject: [PATCH 08/14] allow agent to display images in final message --- backend/src/workflows/prompts.ts | 18 ++++++ frontend/src/pages/Workspace/Message.tsx | 56 +++++++++++++++++-- .../src/pages/Workspace/ToolsContainer.tsx | 2 +- frontend/src/pages/Workspace/Workspace.tsx | 1 + .../src/pages/Workspace/workspace.module.css | 10 ++++ 5 files changed, 82 insertions(+), 5 deletions(-) diff --git a/backend/src/workflows/prompts.ts b/backend/src/workflows/prompts.ts index 36efc05..cfbabe8 100644 --- a/backend/src/workflows/prompts.ts +++ b/backend/src/workflows/prompts.ts @@ -12,6 +12,24 @@ When using browser tools to test or interact with a web application: runCommand: "npm run dev &> devserver.log & sleep 2; tail devserver.log" This redirects output to a log file, runs in background, waits, then shows the log to confirm startup. 3. Use the sandbox's public URLs (provided in the browser_create_session tool description) - NOT localhost/127.0.0.1 + +## Inline Images +When you take screenshots using browser tools, you can reference them inline in your response using the format [codee_image_N] where N is the 1-based index of the image in order of when they were captured during the conversation. + +For example, if you took 2 screenshots, you can reference them as: +- [codee_image_1] - the first screenshot +- [codee_image_2] - the second screenshot + +When referencing an image, place the tag on its own line to display it inline. Example: + +Here is the current state of the page: + +[codee_image_1] + +As you can see, the button is not styled correctly. + + +Furthermore, when prompted with any change that will result in a modification to an existing component/page/etc on the frontend, take a before and after screenshot to show the user the difference. `; export const ORCHESTRATOR_AGENT_SYSTEM_PROMPT = ` diff --git a/frontend/src/pages/Workspace/Message.tsx b/frontend/src/pages/Workspace/Message.tsx index 439ca6f..de1ba74 100644 --- a/frontend/src/pages/Workspace/Message.tsx +++ b/frontend/src/pages/Workspace/Message.tsx @@ -1,13 +1,46 @@ -import type { Message } from '../../lib/types'; +import type { Message, MessageImage } from '../../lib/types'; import style from './workspace.module.css'; -import ToolsContainer from './ToolsContainer'; -import { useState } from 'react'; +import ToolsContainer, { ScreenshotImage } from './ToolsContainer'; +import { useState, useMemo, type ReactNode } from 'react'; interface MessageProps { message: Message; isLastInGroup: boolean; } +function parseMessageContent(content: string, toolCallImages: MessageImage[]): ReactNode[] { + const pattern = /\[codee_image_(\d+)\]/g; + const parts: ReactNode[] = []; + let lastIndex = 0; + let match; + + while ((match = pattern.exec(content)) !== null) { + if (match.index > lastIndex) { + parts.push(content.slice(lastIndex, match.index)); + } + + const imageIndex = parseInt(match[1], 10) - 1; + if (imageIndex >= 0 && imageIndex < toolCallImages.length) { + const image = toolCallImages[imageIndex]; + parts.push( +
+ +
+ ); + } else { + parts.push(match[0]); + } + + lastIndex = pattern.lastIndex; + } + + if (lastIndex < content.length) { + parts.push(content.slice(lastIndex)); + } + + return parts; +} + export default function Message({ message, isLastInGroup }: MessageProps) { const isUser = message.sender === 'USER'; const senderLabel = isUser ? 'You' : 'Agent'; @@ -17,6 +50,21 @@ export default function Message({ message, isLastInGroup }: MessageProps) { const [showFullContent, setShowFullContent] = useState(false); const notLastClass = !isLastInGroup ? style.notLastInGroup : ''; + const toolCallImages = useMemo(() => { + const images: MessageImage[] = []; + for (const toolCall of message.tool_calls) { + if (toolCall.images && toolCall.images.length > 0) { + images.push(...toolCall.images); + } + } + return images; + }, [message.tool_calls]); + + const renderedContent = useMemo(() => { + if (!message.content) return null; + return parseMessageContent(message.content, toolCallImages); + }, [message.content, toolCallImages]); + return (
{!isUser && ( @@ -41,7 +89,7 @@ export default function Message({ message, isLastInGroup }: MessageProps) { ))}
)} - {message.content &&
{message.content}
} + {renderedContent &&
{renderedContent}
} )} {showSenderLabel &&

{senderLabel}

} diff --git a/frontend/src/pages/Workspace/ToolsContainer.tsx b/frontend/src/pages/Workspace/ToolsContainer.tsx index d531b79..face09d 100644 --- a/frontend/src/pages/Workspace/ToolsContainer.tsx +++ b/frontend/src/pages/Workspace/ToolsContainer.tsx @@ -3,7 +3,7 @@ import style from './ToolsContainer.module.css'; import { BsChevronDown, BsX } from 'react-icons/bs'; import { useState } from 'react'; -function ScreenshotImage({ data, mimeType }: { data: string; mimeType: string }) { +export function ScreenshotImage({ data, mimeType }: { data: string; mimeType: string }) { const [isExpanded, setIsExpanded] = useState(false); return ( diff --git a/frontend/src/pages/Workspace/Workspace.tsx b/frontend/src/pages/Workspace/Workspace.tsx index 221b54f..f3d783d 100644 --- a/frontend/src/pages/Workspace/Workspace.tsx +++ b/frontend/src/pages/Workspace/Workspace.tsx @@ -119,6 +119,7 @@ export default function Workspace() { result: eventData.detail ?? '', status: eventData.phase ?? 'running', duration_ms: null, + images: [], }, ]; }); diff --git a/frontend/src/pages/Workspace/workspace.module.css b/frontend/src/pages/Workspace/workspace.module.css index 36de58d..a7ae0c8 100644 --- a/frontend/src/pages/Workspace/workspace.module.css +++ b/frontend/src/pages/Workspace/workspace.module.css @@ -430,6 +430,16 @@ padding-top: 4px; } +.inlineImageWrapper { + display: block; + margin: 6px 0; +} + +.inlineImageWrapper > img { + max-width: 40%; + max-height: 300px; +} + .failedToolCallItem { composes: toolCallItem from './ToolsContainer.module.css'; border: 1px solid rgba(239, 68, 68, 0.5); From fcb233e4192aabcae5d2901296dbcf49f18279ef Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Thu, 15 Jan 2026 06:02:36 -0600 Subject: [PATCH 09/14] fix tools not persisting, improve images showing in messages --- backend/src/providers/codee.ts | 10 +++ backend/src/utils/llm.ts | 83 ++++++++++++++----- backend/src/workflows/prompts.ts | 17 +++- backend/src/workflows/steps.ts | 1 + frontend/src/pages/Workspace/Message.tsx | 58 ++++++++++--- .../src/pages/Workspace/workspace.module.css | 15 +++- 6 files changed, 146 insertions(+), 38 deletions(-) diff --git a/backend/src/providers/codee.ts b/backend/src/providers/codee.ts index 869552a..454b6a3 100644 --- a/backend/src/providers/codee.ts +++ b/backend/src/providers/codee.ts @@ -6,6 +6,7 @@ import { runAgentWorkflow, runOrchestratorAgentWorkflow } from '../workflows/age import { Message, type MessageImage } from '../db/entities/Message'; import { emitStatus } from '../stream/events'; import { ToolCall } from '../db/entities/ToolCall'; +import { WorkspaceTool } from '../db/entities/WorkspaceTool'; import { In } from 'typeorm'; export class CodeeProvider implements CloudProvider { @@ -131,9 +132,18 @@ export class CodeeProvider implements CloudProvider { console.error('Failed to emit status:', err); }); + const workspaceToolRepository = AppDataSource.getRepository(WorkspaceTool); + const workspaceTools = await workspaceToolRepository.find({ + where: { workspace: { id: agent.workspace.id } }, + relations: ['tool'], + }); + const toolSlugs = Array.from(new Set(workspaceTools.map((workspaceTool) => workspaceTool.tool.slugName))); + const payload = { agentId: agent.id, prompt: message, + repositoryFullName: agent.workspace.githubRepositoryName, + toolSlugs, baseBranch: agent.workspace.currentBranch, isOrchestratorAgent: agent.isOrchestratorAgent, }; diff --git a/backend/src/utils/llm.ts b/backend/src/utils/llm.ts index e4c09c9..88fa93f 100644 --- a/backend/src/utils/llm.ts +++ b/backend/src/utils/llm.ts @@ -1,7 +1,8 @@ -import { generateObject, type ModelMessage } from 'ai'; +import { generateObject, type ModelMessage, type ToolCallPart, type ToolResultPart } from 'ai'; import { createOpenAI } from '@ai-sdk/openai'; import { z } from 'zod'; import type { Message } from '../db/entities/Message'; +import type { ToolCall } from '../db/entities/ToolCall'; // import { getPostHog } from './posthog'; const openaiClient = createOpenAI({ @@ -43,26 +44,66 @@ export async function generateTitle(prompt: string): Promise { } export function transformMessagesToModelMessages(previousMessages: Message[]): ModelMessage[] { - return previousMessages.map((message) => { - if (message.sender === 'USER' && message.images.length > 0) { - const content: Array<{ type: 'text'; text: string } | { type: 'image'; image: string; mimeType?: string }> = [ - { type: 'text', text: message.content }, - ]; - for (const image of message.images) { - content.push({ - type: 'image', - image: image.data, - mimeType: image.mimeType, - }); + const result: ModelMessage[] = []; + + for (const message of previousMessages) { + if (message.sender === 'USER') { + // User messages with images + if (message.images && message.images.length > 0) { + const content: Array<{ type: 'text'; text: string } | { type: 'image'; image: string; mimeType?: string }> = [ + { type: 'text', text: message.content }, + ]; + for (const image of message.images) { + content.push({ + type: 'image', + image: image.data, + mimeType: image.mimeType, + }); + } + result.push({ role: 'user', content }); + } else { + result.push({ role: 'user', content: message.content }); + } + } else { + // Agent messages - include tool calls if present + const toolCalls = message.toolCalls || []; + + if (toolCalls.length > 0) { + // Build assistant message with tool calls + const assistantContent: Array<{ type: 'text'; text: string } | ToolCallPart> = []; + + // Add tool calls to assistant content + for (const toolCall of toolCalls) { + assistantContent.push({ + type: 'tool-call', + toolCallId: `tool_${toolCall.id}`, + toolName: toolCall.toolName, + input: toolCall.arguments, + }); + } + + // Add the final text response if present + if (message.content) { + assistantContent.push({ type: 'text', text: message.content }); + } + + result.push({ role: 'assistant', content: assistantContent }); + + // Add tool results as a separate tool message + const toolResults: ToolResultPart[] = toolCalls.map((toolCall: ToolCall) => ({ + type: 'tool-result' as const, + toolCallId: `tool_${toolCall.id}`, + toolName: toolCall.toolName, + output: { type: 'text' as const, value: toolCall.result || '' }, + })); + + result.push({ role: 'tool', content: toolResults }); + } else { + // No tool calls, just add the text content + result.push({ role: 'assistant', content: message.content }); } - return { - role: 'user', - content, - }; } - return { - role: message.sender === 'USER' ? 'user' : 'assistant', - content: message.content, - }; - }); + } + + return result; } diff --git a/backend/src/workflows/prompts.ts b/backend/src/workflows/prompts.ts index cfbabe8..a84834e 100644 --- a/backend/src/workflows/prompts.ts +++ b/backend/src/workflows/prompts.ts @@ -14,11 +14,13 @@ When using browser tools to test or interact with a web application: 3. Use the sandbox's public URLs (provided in the browser_create_session tool description) - NOT localhost/127.0.0.1 ## Inline Images -When you take screenshots using browser tools, you can reference them inline in your response using the format [codee_image_N] where N is the 1-based index of the image in order of when they were captured during the conversation. +When you take screenshots using browser tools, you can reference them inline in your response using the format [codee_image_N] where N is the 1-based index of the image captured during THIS message only. The numbering always starts at 1 for each new response you give. -For example, if you took 2 screenshots, you can reference them as: -- [codee_image_1] - the first screenshot -- [codee_image_2] - the second screenshot +For example, if you took 2 screenshots in your current response: +- [codee_image_1] - the first screenshot in this message +- [codee_image_2] - the second screenshot in this message + +If in a follow-up message you take 2 more screenshots, those would again be [codee_image_1] and [codee_image_2] (not 3 and 4). When referencing an image, place the tag on its own line to display it inline. Example: @@ -28,6 +30,13 @@ Here is the current state of the page: As you can see, the button is not styled correctly. +To display multiple images side by side, place them consecutively without text between them: + +[codee_image_1] +[codee_image_2] + +This will render them in a row for easy comparison. + Furthermore, when prompted with any change that will result in a modification to an existing component/page/etc on the frontend, take a before and after screenshot to show the user the difference. `; diff --git a/backend/src/workflows/steps.ts b/backend/src/workflows/steps.ts index 60edc7f..f57edbb 100644 --- a/backend/src/workflows/steps.ts +++ b/backend/src/workflows/steps.ts @@ -55,6 +55,7 @@ export async function loadPreviousMessages(agentId: number) { return await AppDataSource.getRepository(Message).find({ where: { agent: { id: agentId } }, order: { createdAt: 'ASC' }, + relations: ['toolCalls'], }); } diff --git a/frontend/src/pages/Workspace/Message.tsx b/frontend/src/pages/Workspace/Message.tsx index de1ba74..8c75691 100644 --- a/frontend/src/pages/Workspace/Message.tsx +++ b/frontend/src/pages/Workspace/Message.tsx @@ -8,37 +8,73 @@ interface MessageProps { isLastInGroup: boolean; } +type ParsedPart = { type: 'text'; content: string } | { type: 'image'; image: MessageImage; key: string }; + function parseMessageContent(content: string, toolCallImages: MessageImage[]): ReactNode[] { const pattern = /\[codee_image_(\d+)\]/g; - const parts: ReactNode[] = []; + const parts: ParsedPart[] = []; let lastIndex = 0; let match; while ((match = pattern.exec(content)) !== null) { if (match.index > lastIndex) { - parts.push(content.slice(lastIndex, match.index)); + const textContent = content.slice(lastIndex, match.index); + if (textContent.trim() || textContent.includes('\n')) { + parts.push({ type: 'text', content: textContent }); + } } const imageIndex = parseInt(match[1], 10) - 1; if (imageIndex >= 0 && imageIndex < toolCallImages.length) { - const image = toolCallImages[imageIndex]; - parts.push( -
- -
- ); + parts.push({ type: 'image', image: toolCallImages[imageIndex], key: `image-${match.index}` }); } else { - parts.push(match[0]); + parts.push({ type: 'text', content: match[0] }); } lastIndex = pattern.lastIndex; } if (lastIndex < content.length) { - parts.push(content.slice(lastIndex)); + parts.push({ type: 'text', content: content.slice(lastIndex) }); + } + + const result: ReactNode[] = []; + let i = 0; + while (i < parts.length) { + const part = parts[i]; + if (part.type === 'text') { + result.push(part.content); + i++; + } else { + const imageGroup: ParsedPart[] = [part]; + let j = i + 1; + while (j < parts.length && parts[j].type === 'image') { + imageGroup.push(parts[j]); + j++; + } + + if (imageGroup.length === 1) { + const img = imageGroup[0] as { type: 'image'; image: MessageImage; key: string }; + result.push( +
+ +
+ ); + } else { + result.push( +
+ {imageGroup.map((img) => { + const imgPart = img as { type: 'image'; image: MessageImage; key: string }; + return ; + })} +
+ ); + } + i = j; + } } - return parts; + return result; } export default function Message({ message, isLastInGroup }: MessageProps) { diff --git a/frontend/src/pages/Workspace/workspace.module.css b/frontend/src/pages/Workspace/workspace.module.css index a7ae0c8..931d0c1 100644 --- a/frontend/src/pages/Workspace/workspace.module.css +++ b/frontend/src/pages/Workspace/workspace.module.css @@ -432,12 +432,23 @@ .inlineImageWrapper { display: block; - margin: 6px 0; } .inlineImageWrapper > img { + display: block; max-width: 40%; - max-height: 300px; + max-height: 200px; +} + +.inlineImageRow { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.inlineImageRow > img { + max-width: 200px; + max-height: 150px; } .failedToolCallItem { From 4146c14340640ca792c582f8de1f82baa77f80a7 Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Fri, 16 Jan 2026 22:18:58 -0600 Subject: [PATCH 10/14] improvements to browser agent --- backend/bun.lock | 549 +++++++++++++++++- backend/package.json | 1 + backend/src/db/seed.ts | 6 - backend/src/tools/dynamic.ts | 11 - .../src/tools/kernel/tools/createSession.ts | 2 +- backend/src/workflows/agent.ts | 8 +- backend/src/workflows/helpers/agents.ts | 2 +- backend/src/workflows/llm.ts | 32 +- 8 files changed, 563 insertions(+), 48 deletions(-) diff --git a/backend/bun.lock b/backend/bun.lock index ea5f1ef..646c7d2 100644 --- a/backend/bun.lock +++ b/backend/bun.lock @@ -15,6 +15,7 @@ "@vercel/sandbox": "^1.1.1", "@workos-inc/node": "^7.82.0", "ai": "^6.0.0", + "ai-sdk-provider-gemini-cli": "^2.0.1", "axios": "^1.7.9", "cookie-parser": "^1.4.7", "cors": "^2.8.5", @@ -210,8 +211,32 @@ "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="], + "@google-cloud/common": ["@google-cloud/common@5.0.2", "", { "dependencies": { "@google-cloud/projectify": "^4.0.0", "@google-cloud/promisify": "^4.0.0", "arrify": "^2.0.1", "duplexify": "^4.1.1", "extend": "^3.0.2", "google-auth-library": "^9.0.0", "html-entities": "^2.5.2", "retry-request": "^7.0.0", "teeny-request": "^9.0.0" } }, "sha512-V7bmBKYQyu0eVG2BFejuUjlBt+zrya6vtsKdY+JxMM/dNntPF41vZ9+LhOshEUH01zOHEqBSvI7Dad7ZS6aUeA=="], + + "@google-cloud/logging": ["@google-cloud/logging@11.2.1", "", { "dependencies": { "@google-cloud/common": "^5.0.0", "@google-cloud/paginator": "^5.0.0", "@google-cloud/projectify": "^4.0.0", "@google-cloud/promisify": "4.0.0", "@opentelemetry/api": "^1.7.0", "arrify": "^2.0.1", "dot-prop": "^6.0.0", "eventid": "^2.0.0", "extend": "^3.0.2", "gcp-metadata": "^6.0.0", "google-auth-library": "^9.0.0", "google-gax": "^4.0.3", "on-finished": "^2.3.0", "pumpify": "^2.0.1", "stream-events": "^1.0.5", "uuid": "^9.0.0" } }, "sha512-2h9HBJG3OAsvzXmb81qXmaTPfXYU7KJTQUxunoOKFGnY293YQ/eCkW1Y5mHLocwpEqeqQYT/Qvl6Tk+Q7PfStw=="], + + "@google-cloud/opentelemetry-cloud-monitoring-exporter": ["@google-cloud/opentelemetry-cloud-monitoring-exporter@0.21.0", "", { "dependencies": { "@google-cloud/opentelemetry-resource-util": "^3.0.0", "@google-cloud/precise-date": "^4.0.0", "google-auth-library": "^9.0.0", "googleapis": "^137.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/core": "^2.0.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/sdk-metrics": "^2.0.0" } }, "sha512-+lAew44pWt6rA4l8dQ1gGhH7Uo95wZKfq/GBf9aEyuNDDLQ2XppGEEReu6ujesSqTtZ8ueQFt73+7SReSHbwqg=="], + + "@google-cloud/opentelemetry-cloud-trace-exporter": ["@google-cloud/opentelemetry-cloud-trace-exporter@3.0.0", "", { "dependencies": { "@google-cloud/opentelemetry-resource-util": "^3.0.0", "@grpc/grpc-js": "^1.1.8", "@grpc/proto-loader": "^0.8.0", "google-auth-library": "^9.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@opentelemetry/core": "^2.0.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/sdk-trace-base": "^2.0.0" } }, "sha512-mUfLJBFo+ESbO0dAGboErx2VyZ7rbrHcQvTP99yH/J72dGaPbH2IzS+04TFbTbEd1VW5R9uK3xq2CqawQaG+1Q=="], + + "@google-cloud/opentelemetry-resource-util": ["@google-cloud/opentelemetry-resource-util@3.0.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.22.0", "gcp-metadata": "^6.0.0" }, "peerDependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/resources": "^2.0.0" } }, "sha512-CGR/lNzIfTKlZoZFfS6CkVzx+nsC9gzy6S8VcyaLegfEJbiPjxbMLP7csyhJTvZe/iRRcQJxSk0q8gfrGqD3/Q=="], + + "@google-cloud/paginator": ["@google-cloud/paginator@5.0.2", "", { "dependencies": { "arrify": "^2.0.0", "extend": "^3.0.2" } }, "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg=="], + + "@google-cloud/precise-date": ["@google-cloud/precise-date@4.0.0", "", {}, "sha512-1TUx3KdaU3cN7nfCdNf+UVqA/PSX29Cjcox3fZZBtINlRrXVTmUkQnCKv2MbBUbCopbK4olAT1IHl76uZyCiVA=="], + + "@google-cloud/projectify": ["@google-cloud/projectify@4.0.0", "", {}, "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA=="], + + "@google-cloud/promisify": ["@google-cloud/promisify@4.0.0", "", {}, "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g=="], + + "@google/gemini-cli-core": ["@google/gemini-cli-core@0.22.4", "", { "dependencies": { "@google-cloud/logging": "^11.2.1", "@google-cloud/opentelemetry-cloud-monitoring-exporter": "^0.21.0", "@google-cloud/opentelemetry-cloud-trace-exporter": "^3.0.0", "@google/genai": "1.30.0", "@iarna/toml": "^2.2.5", "@joshua.litt/get-ripgrep": "^0.0.3", "@modelcontextprotocol/sdk": "^1.23.0", "@opentelemetry/api": "^1.9.0", "@opentelemetry/exporter-logs-otlp-grpc": "^0.203.0", "@opentelemetry/exporter-logs-otlp-http": "^0.203.0", "@opentelemetry/exporter-metrics-otlp-grpc": "^0.203.0", "@opentelemetry/exporter-metrics-otlp-http": "^0.203.0", "@opentelemetry/exporter-trace-otlp-grpc": "^0.203.0", "@opentelemetry/exporter-trace-otlp-http": "^0.203.0", "@opentelemetry/instrumentation-http": "^0.203.0", "@opentelemetry/resource-detector-gcp": "^0.40.0", "@opentelemetry/sdk-node": "^0.203.0", "@types/glob": "^8.1.0", "@types/html-to-text": "^9.0.4", "@xterm/headless": "5.5.0", "ajv": "^8.17.1", "ajv-formats": "^3.0.0", "chardet": "^2.1.0", "diff": "^7.0.0", "dotenv": "^17.1.0", "fast-levenshtein": "^2.0.6", "fast-uri": "^3.0.6", "fdir": "^6.4.6", "fzf": "^0.5.2", "glob": "^12.0.0", "google-auth-library": "^9.11.0", "html-to-text": "^9.0.5", "https-proxy-agent": "^7.0.6", "ignore": "^7.0.0", "marked": "^15.0.12", "mime": "4.0.7", "mnemonist": "^0.40.3", "open": "^10.1.2", "picomatch": "^4.0.1", "read-package-up": "^11.0.0", "shell-quote": "^1.8.3", "simple-git": "^3.28.0", "strip-ansi": "^7.1.0", "tree-sitter-bash": "^0.25.0", "undici": "^7.10.0", "web-tree-sitter": "^0.25.10", "ws": "^8.18.0", "zod": "^3.25.76" }, "optionalDependencies": { "@lydell/node-pty": "1.1.0", "@lydell/node-pty-darwin-arm64": "1.1.0", "@lydell/node-pty-darwin-x64": "1.1.0", "@lydell/node-pty-linux-x64": "1.1.0", "@lydell/node-pty-win32-arm64": "1.1.0", "@lydell/node-pty-win32-x64": "1.1.0", "node-pty": "^1.0.0" } }, "sha512-tJXajzxWXkSU8jVfwPG6rEFtUg9Bi3I+YAcTUzLEeaNITHJX+1IV0cVvi3/qguz6dWAnYM0mQ3U9jXvfyvIDPg=="], + "@google/genai": ["@google/genai@1.34.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.24.0" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-vu53UMPvjmb7PGzlYu6Tzxso8Dfhn+a7eQFaS2uNemVtDZKwzSpJ5+ikqBbXplF7RGB1STcVDqCkPvquiwb2sw=="], + "@grpc/grpc-js": ["@grpc/grpc-js@1.14.3", "", { "dependencies": { "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" } }, "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA=="], + + "@grpc/proto-loader": ["@grpc/proto-loader@0.8.0", "", { "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", "protobufjs": "^7.5.3", "yargs": "^17.7.2" }, "bin": { "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" } }, "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ=="], + "@hono/node-server": ["@hono/node-server@1.19.7", "", { "peerDependencies": { "hono": "^4" } }, "sha512-vUcD0uauS7EU2caukW8z5lJKtoGMokxNbJtBiwHgpqxEXokaHCBkQUmCHhjFB1VUTWdqj25QoMkMKzgjq+uhrw=="], "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], @@ -222,6 +247,8 @@ "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + "@iarna/toml": ["@iarna/toml@2.2.5", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="], + "@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="], "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], @@ -274,8 +301,14 @@ "@ioredis/commands": ["@ioredis/commands@1.4.0", "", {}, "sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ=="], + "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], + + "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="], + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + "@joshua.litt/get-ripgrep": ["@joshua.litt/get-ripgrep@0.0.3", "", { "dependencies": { "@lvce-editor/verror": "^1.6.0", "execa": "^9.5.2", "extract-zip": "^2.0.1", "fs-extra": "^11.3.0", "got": "^14.4.5", "path-exists": "^5.0.0", "xdg-basedir": "^5.1.0" } }, "sha512-rycdieAKKqXi2bsM7G2ayDiNk5CAX8ZOzsTQsirfOqUKPef04Xw40BWGGyimaOOuvPgLWYt3tPnLLG3TvPXi5Q=="], + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], @@ -286,6 +319,14 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + "@js-sdsl/ordered-map": ["@js-sdsl/ordered-map@4.4.2", "", {}, "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw=="], + + "@keyv/serialize": ["@keyv/serialize@1.1.1", "", {}, "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA=="], + + "@kwsites/file-exists": ["@kwsites/file-exists@1.1.1", "", { "dependencies": { "debug": "^4.1.1" } }, "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw=="], + + "@kwsites/promise-deferred": ["@kwsites/promise-deferred@1.1.1", "", {}, "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw=="], + "@langchain/core": ["@langchain/core@1.1.8", "", { "dependencies": { "@cfworker/json-schema": "^4.0.2", "ansi-styles": "^5.0.0", "camelcase": "6", "decamelize": "1.2.0", "js-tiktoken": "^1.0.12", "langsmith": ">=0.4.0 <1.0.0", "mustache": "^4.2.0", "p-queue": "^6.6.2", "uuid": "^10.0.0", "zod": "^3.25.76 || ^4" } }, "sha512-kIUidOgc0ZdyXo4Ahn9Zas+OayqOfk4ZoKPi7XaDipNSWSApc2+QK5BVcjvwtzxstsNOrmXJiJWEN6WPF/MvAw=="], "@langchain/langgraph": ["@langchain/langgraph@1.0.7", "", { "dependencies": { "@langchain/langgraph-checkpoint": "^1.0.0", "@langchain/langgraph-sdk": "~1.3.1", "uuid": "^10.0.0" }, "peerDependencies": { "@langchain/core": "^1.0.1", "zod": "^3.25.32 || ^4.1.0", "zod-to-json-schema": "^3.x" }, "optionalPeers": ["zod-to-json-schema"] }, "sha512-EBGqNOWoRiEoLUaeuiXRpUM8/DE6QcwiirNyd97XhezStebBoTTilWH8CUt6S94JRGl5zwfBBRHfzotDnZS/eA=="], @@ -296,6 +337,22 @@ "@langchain/openai": ["@langchain/openai@0.6.17", "", { "dependencies": { "js-tiktoken": "^1.0.12", "openai": "5.12.2", "zod": "^3.25.32" }, "peerDependencies": { "@langchain/core": ">=0.3.68 <0.4.0" } }, "sha512-JVSzD+FL5v/2UQxKd+ikB1h4PQOtn0VlK8nqW2kPp0fshItCv4utrjBKXC/rubBnSXoRTyonBINe8QRZ6OojVQ=="], + "@lvce-editor/verror": ["@lvce-editor/verror@1.7.0", "", {}, "sha512-+LGuAEIC2L7pbvkyAQVWM2Go0dAy+UWEui28g07zNtZsCBhm+gusBK8PNwLJLV5Jay+TyUYuwLIbJdjLLzqEBg=="], + + "@lydell/node-pty": ["@lydell/node-pty@1.1.0", "", { "optionalDependencies": { "@lydell/node-pty-darwin-arm64": "1.1.0", "@lydell/node-pty-darwin-x64": "1.1.0", "@lydell/node-pty-linux-arm64": "1.1.0", "@lydell/node-pty-linux-x64": "1.1.0", "@lydell/node-pty-win32-arm64": "1.1.0", "@lydell/node-pty-win32-x64": "1.1.0" } }, "sha512-VDD8LtlMTOrPKWMXUAcB9+LTktzuunqrMwkYR1DMRBkS6LQrCt+0/Ws1o2rMml/n3guePpS7cxhHF7Nm5K4iMw=="], + + "@lydell/node-pty-darwin-arm64": ["@lydell/node-pty-darwin-arm64@1.1.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-7kFD+owAA61qmhJCtoMbqj3Uvff3YHDiU+4on5F2vQdcMI3MuwGi7dM6MkFG/yuzpw8LF2xULpL71tOPUfxs0w=="], + + "@lydell/node-pty-darwin-x64": ["@lydell/node-pty-darwin-x64@1.1.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-XZdvqj5FjAMjH8bdp0YfaZjur5DrCIDD1VYiE9EkkYVMDQqRUPHYV3U8BVEQVT9hYfjmpr7dNaELF2KyISWSNA=="], + + "@lydell/node-pty-linux-arm64": ["@lydell/node-pty-linux-arm64@1.1.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-yyDBmalCfHpLiQMT2zyLcqL2Fay4Xy7rIs8GH4dqKLnEviMvPGOK7LADVkKAsbsyXBSISL3Lt1m1MtxhPH6ckg=="], + + "@lydell/node-pty-linux-x64": ["@lydell/node-pty-linux-x64@1.1.0", "", { "os": "linux", "cpu": "x64" }, "sha512-NcNqRTD14QT+vXcEuqSSvmWY+0+WUBn2uRE8EN0zKtDpIEr9d+YiFj16Uqds6QfcLCHfZmC+Ls7YzwTaqDnanA=="], + + "@lydell/node-pty-win32-arm64": ["@lydell/node-pty-win32-arm64@1.1.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-JOMbCou+0fA7d/m97faIIfIU0jOv8sn2OR7tI45u3AmldKoKoLP8zHY6SAvDDnI3fccO1R2HeR1doVjpS7HM0w=="], + + "@lydell/node-pty-win32-x64": ["@lydell/node-pty-win32-x64@1.1.0", "", { "os": "win32", "cpu": "x64" }, "sha512-3N56BZ+WDFnUMYRtsrr7Ky2mhWGl9xXcyqR6cexfuCqcz9RNWL+KoXRv/nZylY5dYaXkft4JaR1uVu+roiZDAw=="], + "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.25.1", "", { "dependencies": { "@hono/node-server": "^1.19.7", "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-yO28oVFFC7EBoiKdAn+VqRm+plcfv4v0xp6osG/VsCB0NlPZWi87ajbCZZ8f/RvOFLEu7//rSRmuZZ7lMoe3gQ=="], "@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=="], @@ -336,6 +393,64 @@ "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], + "@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.203.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ=="], + + "@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@2.0.1", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-XuY23lSI3d4PEqKA+7SLtAgwqIfc6E/E9eAQWLN1vlpC53ybO3o6jW4BsXo1xvz9lYyyWItfQDDLzezER01mCw=="], + + "@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=="], + + "@opentelemetry/exporter-logs-otlp-grpc": ["@opentelemetry/exporter-logs-otlp-grpc@0.203.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/sdk-logs": "0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-g/2Y2noc/l96zmM+g0LdeuyYKINyBwN6FJySoU15LHPLcMN/1a0wNk2SegwKcxrRdE7Xsm7fkIR5n6XFe3QpPw=="], + + "@opentelemetry/exporter-logs-otlp-http": ["@opentelemetry/exporter-logs-otlp-http@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/sdk-logs": "0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-s0hys1ljqlMTbXx2XiplmMJg9wG570Z5lH7wMvrZX6lcODI56sG4HL03jklF63tBeyNwK2RV1/ntXGo3HgG4Qw=="], + + "@opentelemetry/exporter-logs-otlp-proto": ["@opentelemetry/exporter-logs-otlp-proto@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-logs": "0.203.0", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-nl/7S91MXn5R1aIzoWtMKGvqxgJgepB/sH9qW0rZvZtabnsjbf8OQ1uSx3yogtvLr0GzwD596nQKz2fV7q2RBw=="], + + "@opentelemetry/exporter-metrics-otlp-grpc": ["@opentelemetry/exporter-metrics-otlp-grpc@0.203.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-metrics": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-FCCj9nVZpumPQSEI57jRAA89hQQgONuoC35Lt+rayWY/mzCAc6BQT7RFyFaZKJ2B7IQ8kYjOCPsF/HGFWjdQkQ=="], + + "@opentelemetry/exporter-metrics-otlp-http": ["@opentelemetry/exporter-metrics-otlp-http@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-metrics": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HFSW10y8lY6BTZecGNpV3GpoSy7eaO0Z6GATwZasnT4bEsILp8UJXNG5OmEsz4SdwCSYvyCbTJdNbZP3/8LGCQ=="], + + "@opentelemetry/exporter-metrics-otlp-proto": ["@opentelemetry/exporter-metrics-otlp-proto@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-metrics": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-OZnhyd9npU7QbyuHXFEPVm3LnjZYifuKpT3kTnF84mXeEQ84pJJZgyLBpU4FSkSwUkt/zbMyNAI7y5+jYTWGIg=="], + + "@opentelemetry/exporter-prometheus": ["@opentelemetry/exporter-prometheus@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-metrics": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-2jLuNuw5m4sUj/SncDf/mFPabUxMZmmYetx5RKIMIQyPnl6G6ooFzfeE8aXNRf8YD1ZXNlCnRPcISxjveGJHNg=="], + + "@opentelemetry/exporter-trace-otlp-grpc": ["@opentelemetry/exporter-trace-otlp-grpc@0.203.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-322coOTf81bm6cAA8+ML6A+m4r2xTCdmAZzGNTboPXRzhwPt4JEmovsFAs+grpdarObd68msOJ9FfH3jxM6wqA=="], + + "@opentelemetry/exporter-trace-otlp-http": ["@opentelemetry/exporter-trace-otlp-http@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-ZDiaswNYo0yq/cy1bBLJFe691izEJ6IgNmkjm4C6kE9ub/OMQqDXORx2D2j8fzTBTxONyzusbaZlqtfmyqURPw=="], + + "@opentelemetry/exporter-trace-otlp-proto": ["@opentelemetry/exporter-trace-otlp-proto@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-1xwNTJ86L0aJmWRwENCJlH4LULMG2sOXWIVw+Szta4fkqKVY50Eo4HoVKKq6U9QEytrWCr8+zjw0q/ZOeXpcAQ=="], + + "@opentelemetry/exporter-zipkin": ["@opentelemetry/exporter-zipkin@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-a9eeyHIipfdxzCfc2XPrE+/TI3wmrZUDFtG2RRXHSbZZULAny7SyybSvaDvS77a7iib5MPiAvluwVvbGTsHxsw=="], + + "@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ=="], + + "@opentelemetry/instrumentation-http": ["@opentelemetry/instrumentation-http@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/instrumentation": "0.203.0", "@opentelemetry/semantic-conventions": "^1.29.0", "forwarded-parse": "2.1.2" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-y3uQAcCOAwnO6vEuNVocmpVzG3PER6/YZqbPbbffDdJ9te5NkHEkfSMNzlC3+v7KlE+WinPGc3N7MR30G1HY2g=="], + + "@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-transformer": "0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ=="], + + "@opentelemetry/otlp-grpc-exporter-base": ["@opentelemetry/otlp-grpc-exporter-base@0.203.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-te0Ze1ueJF+N/UOFl5jElJW4U0pZXQ8QklgSfJ2linHN0JJsuaHG8IabEUi2iqxY8ZBDlSiz1Trfv5JcjWWWwQ=="], + + "@opentelemetry/otlp-transformer": ["@opentelemetry/otlp-transformer@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-logs": "0.203.0", "@opentelemetry/sdk-metrics": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1", "protobufjs": "^7.3.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A=="], + + "@opentelemetry/propagator-b3": ["@opentelemetry/propagator-b3@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-Hc09CaQ8Tf5AGLmf449H726uRoBNGPBL4bjr7AnnUpzWMvhdn61F78z9qb6IqB737TffBsokGAK1XykFEZ1igw=="], + + "@opentelemetry/propagator-jaeger": ["@opentelemetry/propagator-jaeger@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-7PMdPBmGVH2eQNb/AtSJizQNgeNTfh6jQFqys6lfhd6P4r+m/nTh3gKPPpaCXVdRQ+z93vfKk+4UGty390283w=="], + + "@opentelemetry/resource-detector-gcp": ["@opentelemetry/resource-detector-gcp@0.40.3", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/resources": "^2.0.0", "gcp-metadata": "^6.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-C796YjBA5P1JQldovApYfFA/8bQwFfpxjUbOtGhn1YZkVTLoNQN+kvBwgALfTPWzug6fWsd0xhn9dzeiUcndag=="], + + "@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=="], + + "@opentelemetry/sdk-logs": ["@opentelemetry/sdk-logs@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw=="], + + "@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=="], + + "@opentelemetry/sdk-node": ["@opentelemetry/sdk-node@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/exporter-logs-otlp-grpc": "0.203.0", "@opentelemetry/exporter-logs-otlp-http": "0.203.0", "@opentelemetry/exporter-logs-otlp-proto": "0.203.0", "@opentelemetry/exporter-metrics-otlp-grpc": "0.203.0", "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", "@opentelemetry/exporter-metrics-otlp-proto": "0.203.0", "@opentelemetry/exporter-prometheus": "0.203.0", "@opentelemetry/exporter-trace-otlp-grpc": "0.203.0", "@opentelemetry/exporter-trace-otlp-http": "0.203.0", "@opentelemetry/exporter-trace-otlp-proto": "0.203.0", "@opentelemetry/exporter-zipkin": "2.0.1", "@opentelemetry/instrumentation": "0.203.0", "@opentelemetry/propagator-b3": "2.0.1", "@opentelemetry/propagator-jaeger": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-logs": "0.203.0", "@opentelemetry/sdk-metrics": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1", "@opentelemetry/sdk-trace-node": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-zRMvrZGhGVMvAbbjiNQW3eKzW/073dlrSiAKPVWmkoQzah9wfynpVPeL55f9fVIm0GaBxTLcPeukWGy0/Wj7KQ=="], + + "@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ=="], + + "@opentelemetry/sdk-trace-node": ["@opentelemetry/sdk-trace-node@2.0.1", "", { "dependencies": { "@opentelemetry/context-async-hooks": "2.0.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-UhdbPF19pMpBtCWYP5lHbTogLWx9N0EBxtdagvkn5YtsAnCBZzL7SjktG+ZmupRgifsHMjwUaCCaVmqGfSADmA=="], + + "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.38.0", "", {}, "sha512-kocjix+/sSggfJhwXqClZ3i9Y/MI0fp7b+g7kCRm6psy2dsf8uApTRclwG18h8Avm7C9+fnt+O36PspJ/OzoWg=="], + "@oxc-minify/binding-android-arm64": ["@oxc-minify/binding-android-arm64@0.96.0", "", { "os": "android", "cpu": "arm64" }, "sha512-lzeIEMu/v6Y+La5JSesq4hvyKtKBq84cgQpKYTYM/yGuNk2tfd5Ha31hnC+mTh48lp/5vZH+WBfjVUjjINCfug=="], "@oxc-minify/binding-darwin-arm64": ["@oxc-minify/binding-darwin-arm64@0.96.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-i0LkJAUXb4BeBFrJQbMKQPoxf8+cFEffDyLSb7NEzzKuPcH8qrVsnEItoOzeAdYam8Sr6qCHVwmBNEQzl7PWpw=="], @@ -410,6 +525,26 @@ "@posthog/ai": ["@posthog/ai@7.3.0", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.2", "@google/genai": "^1.33.0", "@langchain/core": "^1.1.5", "langchain": "^1.2.0", "openai": "^6.10.0", "uuid": "^11.1.0", "zod": "^4.1.13" }, "peerDependencies": { "@ai-sdk/provider": "^2.0.0 || ^3.0.0-beta.0", "posthog-node": "^5.0.0" }, "optionalPeers": ["@ai-sdk/provider"] }, "sha512-8AngpYfRklUoGnKbh3VocAvHR0tgRnk+wAB3s8AEsOUNn5DrCfCitloUW5vTLmFBUAj7UMULkMBBWbALD9MkrQ=="], + "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="], + + "@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="], + + "@protobufjs/codegen": ["@protobufjs/codegen@2.0.4", "", {}, "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="], + + "@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.0", "", {}, "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="], + + "@protobufjs/fetch": ["@protobufjs/fetch@1.1.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ=="], + + "@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="], + + "@protobufjs/inquire": ["@protobufjs/inquire@1.1.0", "", {}, "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="], + + "@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="], + + "@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="], + + "@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.55.1", "", { "os": "android", "cpu": "arm" }, "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg=="], "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.55.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg=="], @@ -460,6 +595,14 @@ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.55.1", "", { "os": "win32", "cpu": "x64" }, "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw=="], + "@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="], + + "@selderee/plugin-htmlparser2": ["@selderee/plugin-htmlparser2@0.11.0", "", { "dependencies": { "domhandler": "^5.0.3", "selderee": "^0.11.0" } }, "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ=="], + + "@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="], + + "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="], + "@smithy/abort-controller": ["@smithy/abort-controller@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-rzMY6CaKx2qxrbYbqjXWS0plqEy7LOdKHS0bg4ixJ6aoGDPNUcLWk/FRNuCILh7GKLG9TFUXYYeQQldMBBwuyw=="], "@smithy/config-resolver": ["@smithy/config-resolver@4.4.5", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "tslib": "^2.6.2" } }, "sha512-HAGoUAFYsUkoSckuKbCPayECeMim8pOu+yLy1zOxt1sifzEbrsRpYa+mKcMdiHKMeiqOibyPG0sFJnmaV/OGEg=="], @@ -572,6 +715,8 @@ "@swc/types": ["@swc/types@0.1.25", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g=="], + "@tootallnate/once": ["@tootallnate/once@2.0.0", "", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="], + "@trpc/server": ["@trpc/server@11.8.1", "", { "peerDependencies": { "typescript": ">=5.7.2" } }, "sha512-P4rzZRpEL7zDFgjxK65IdyH0e41FMFfTkQkuq0BA5tKcr7E6v9/v38DEklCpoDN6sPiB1Sigy/PUEzHENhswDA=="], "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], @@ -584,6 +729,8 @@ "@types/bun": ["@types/bun@1.3.5", "", { "dependencies": { "bun-types": "1.3.5" } }, "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w=="], + "@types/caseless": ["@types/caseless@0.12.5", "", {}, "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg=="], + "@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="], "@types/content-disposition": ["@types/content-disposition@0.5.9", "", {}, "sha512-8uYXI3Gw35MhiVYhG3s295oihrxRyytcRHjSjqnqZVDDy/xcGBRny7+Xj1Wgfhv5QzRtN2hB2dVRBUX9XW3UcQ=="], @@ -616,8 +763,14 @@ "@types/express-serve-static-core": ["@types/express-serve-static-core@5.1.1", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A=="], + "@types/glob": ["@types/glob@8.1.0", "", { "dependencies": { "@types/minimatch": "^5.1.2", "@types/node": "*" } }, "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w=="], + + "@types/html-to-text": ["@types/html-to-text@9.0.4", "", {}, "sha512-pUY3cKH/Nm2yYrEmDlPR1mR7yszjGx4DrwPjQ702C4/D5CwHuZTgZdIdwPkRbcuhs7BAh2L5rg3CL5cbRiGTCQ=="], + "@types/http-assert": ["@types/http-assert@1.5.6", "", {}, "sha512-TTEwmtjgVbYAzZYWyeHPrrtWnfVkm8tQkP8P21uQifPgMRgjrow3XDEYqucuC8SKZJT7pUnhU/JymvjggxO9vw=="], + "@types/http-cache-semantics": ["@types/http-cache-semantics@4.0.4", "", {}, "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA=="], + "@types/http-errors": ["@types/http-errors@2.0.5", "", {}, "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg=="], "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], @@ -628,28 +781,40 @@ "@types/koa-compose": ["@types/koa-compose@3.2.9", "", { "dependencies": { "@types/koa": "*" } }, "sha512-BroAZ9FTvPiCy0Pi8tjD1OfJ7bgU1gQf0eR6e1Vm+JJATy9eKOG3hQMFtMciMawiSOVnLMdmUOC46s7HBhSTsA=="], + "@types/long": ["@types/long@4.0.2", "", {}, "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA=="], + "@types/mime": ["@types/mime@1.3.5", "", {}, "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="], + "@types/minimatch": ["@types/minimatch@5.1.2", "", {}, "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA=="], + "@types/morgan": ["@types/morgan@1.9.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-sS4A1zheMvsADRVfT0lYbJ4S9lmsey8Zo2F7cnbYjWHP67Q0AwMYuuzLlkIM2N8gAbb9cubhIVFwcIN2XyYCkA=="], "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], "@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="], + "@types/normalize-package-data": ["@types/normalize-package-data@2.4.4", "", {}, "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA=="], + "@types/pg": ["@types/pg@8.16.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ=="], "@types/qs": ["@types/qs@6.14.0", "", {}, "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ=="], "@types/range-parser": ["@types/range-parser@1.2.7", "", {}, "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="], + "@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/send": ["@types/send@1.2.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ=="], "@types/serve-static": ["@types/serve-static@2.2.0", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*" } }, "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ=="], + "@types/tough-cookie": ["@types/tough-cookie@4.0.5", "", {}, "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="], + "@types/uuid": ["@types/uuid@10.0.0", "", {}, "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ=="], + "@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.50.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.50.1", "@typescript-eslint/type-utils": "8.50.1", "@typescript-eslint/utils": "8.50.1", "@typescript-eslint/visitor-keys": "8.50.1", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.50.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-PKhLGDq3JAg0Jk/aK890knnqduuI/Qj+udH7wCf0217IGi4gt+acgCyPVe79qoT+qKUvHMDQkwJeKW9fwl8Cyw=="], "@typescript-eslint/parser": ["@typescript-eslint/parser@8.50.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.50.1", "@typescript-eslint/types": "8.50.1", "@typescript-eslint/typescript-estree": "8.50.1", "@typescript-eslint/visitor-keys": "8.50.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-hM5faZwg7aVNa819m/5r7D0h0c9yC4DUlWAOvHAtISdFTc8xB86VmX5Xqabrama3wIPJ/q9RbGS1worb6JfnMg=="], @@ -716,14 +881,20 @@ "@workos-inc/node": ["@workos-inc/node@7.82.0", "", { "dependencies": { "iron-session": "~6.3.1", "jose": "~5.6.3", "leb": "^1.0.0", "qs": "6.14.1" } }, "sha512-8h6XjIJf8nqNGYQMkWsjZ72WXMtzqrb4Azz39schXWoSRmwoK6tK+GpeAviJ9slddiJdOcp0Ht9/r+L6pGQMCg=="], + "@xterm/headless": ["@xterm/headless@5.5.0", "", {}, "sha512-5xXB7kdQlFBP82ViMJTwwEc3gKCLGKR/eoxQm4zge7GPBl86tCdI0IdPJjoKd8mUSFXz5V7i/25sfsEkP4j46g=="], + "@xyflow/react": ["@xyflow/react@12.9.3", "", { "dependencies": { "@xyflow/system": "0.0.73", "classcat": "^5.0.3", "zustand": "^4.4.0" }, "peerDependencies": { "react": ">=17", "react-dom": ">=17" } }, "sha512-PSWoJ8vHiEqSIkLIkge+0eiHWiw4C6dyFDA03VKWJkqbU4A13VlDIVwKqf/Znuysn2GQw/zA61zpHE4rGgax7Q=="], "@xyflow/system": ["@xyflow/system@0.0.73", "", { "dependencies": { "@types/d3-drag": "^3.0.7", "@types/d3-interpolate": "^3.0.4", "@types/d3-selection": "^3.0.10", "@types/d3-transition": "^3.0.8", "@types/d3-zoom": "^3.0.8", "d3-drag": "^3.0.0", "d3-interpolate": "^3.0.1", "d3-selection": "^3.0.0", "d3-zoom": "^3.0.0" } }, "sha512-C2ymH2V4mYDkdVSiRx0D7R0s3dvfXiupVBcko6tXP5K4tVdSBMo22/e3V9yRNdn+2HQFv44RFKzwOyCcUUDAVQ=="], + "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], + "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "acorn-import-attributes": ["acorn-import-attributes@1.9.5", "", { "peerDependencies": { "acorn": "^8" } }, "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ=="], + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], @@ -732,6 +903,8 @@ "ai": ["ai@6.0.5", "", { "dependencies": { "@ai-sdk/gateway": "3.0.4", "@ai-sdk/provider": "3.0.1", "@ai-sdk/provider-utils": "4.0.2", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-CKL3dDHedWskC6EY67LrULonZBU9vL+Bwa+xQEcprBhJfxpogntG3utjiAkYuy5ZQatyWk+SmWG8HLvcnhvbRg=="], + "ai-sdk-provider-gemini-cli": ["ai-sdk-provider-gemini-cli@2.0.1", "", { "dependencies": { "@ai-sdk/provider": "^3.0.0", "@ai-sdk/provider-utils": "^4.0.1", "@google/gemini-cli-core": "0.22.4", "@google/genai": "1.30.0", "google-auth-library": "^9.11.0", "zod-to-json-schema": "3.25.0" }, "peerDependencies": { "zod": "^3.0.0 || ^4.0.0" } }, "sha512-v9Oc9irtWalFjODdj6nUFg0ifNJYm6IiWoafNdsJINmgE2k5JC0gEouypPsGoX9RAkIlOsJiE3ujbd+6nUqXxw=="], + "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], @@ -740,7 +913,7 @@ "ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="], - "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], @@ -752,6 +925,8 @@ "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], + "arrify": ["arrify@2.0.1", "", {}, "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug=="], + "asn1js": ["asn1js@3.0.7", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", "tslib": "^2.8.1" } }, "sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ=="], "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], @@ -792,6 +967,8 @@ "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], + "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], + "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], "builtin-modules": ["builtin-modules@5.0.0", "", {}, "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg=="], @@ -800,10 +977,16 @@ "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], + "byte-counter": ["byte-counter@0.1.0", "", {}, "sha512-jheRLVMeUKrDBjVw2O5+k4EvR4t9wtxHL+bo/LxfkxsVeuGMy3a5SEGgXdAFA4FSzTrU8rQXQIrsZ3oBq5a0pQ=="], + "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], "c12": ["c12@3.3.3", "", { "dependencies": { "chokidar": "^5.0.0", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^17.2.3", "exsolve": "^1.0.8", "giget": "^2.0.0", "jiti": "^2.6.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "*" }, "optionalPeers": ["magicast"] }, "sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q=="], + "cacheable-lookup": ["cacheable-lookup@7.0.0", "", {}, "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w=="], + + "cacheable-request": ["cacheable-request@13.0.18", "", { "dependencies": { "@types/http-cache-semantics": "^4.0.4", "get-stream": "^9.0.1", "http-cache-semantics": "^4.2.0", "keyv": "^5.5.5", "mimic-response": "^4.0.0", "normalize-url": "^8.1.1", "responselike": "^4.0.2" } }, "sha512-rFWadDRKJs3s2eYdXlGggnBZKG7MTblkFBB0YllFds+UYnfogDp2wcR6JN97FhRkHTvq59n2vhNoHNZn29dh/Q=="], + "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], @@ -818,10 +1001,14 @@ "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "chardet": ["chardet@2.1.1", "", {}, "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ=="], + "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], "citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="], + "cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="], + "classcat": ["classcat@5.0.5", "", {}, "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w=="], "clean-stack": ["clean-stack@3.0.1", "", { "dependencies": { "escape-string-regexp": "4.0.0" } }, "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg=="], @@ -908,10 +1095,14 @@ "decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="], + "decompress-response": ["decompress-response@10.0.0", "", { "dependencies": { "mimic-response": "^4.0.0" } }, "sha512-oj7KWToJuuxlPr7VV0vabvxEIiqNMo+q0NueIiL3XhtwC6FVOX7Hr1c0C4eD0bmf7Zr+S/dSf2xvkH3Ad6sU3Q=="], + "dedent": ["dedent@1.7.1", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg=="], "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], + "default-browser": ["default-browser@5.4.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg=="], "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="], @@ -938,14 +1129,28 @@ "devalue": ["devalue@5.6.0", "", {}, "sha512-BaD1s81TFFqbD6Uknni42TrolvEWA1Ih5L+OiHWmi4OYMJVwAYPGtha61I9KxTf52OvVHozHyjPu8zljqdF3uA=="], + "diff": ["diff@7.0.0", "", {}, "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw=="], + "diff-match-patch": ["diff-match-patch@1.0.5", "", {}, "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw=="], "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], + "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], + + "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], + + "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], + + "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], + + "dot-prop": ["dot-prop@6.0.1", "", { "dependencies": { "is-obj": "^2.0.0" } }, "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA=="], + "dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + "duplexify": ["duplexify@4.1.3", "", { "dependencies": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", "readable-stream": "^3.1.1", "stream-shift": "^1.0.2" } }, "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA=="], + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], "easy-table": ["easy-table@1.2.0", "", { "dependencies": { "ansi-regex": "^5.0.1" }, "optionalDependencies": { "wcwidth": "^1.0.1" } }, "sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww=="], @@ -960,8 +1165,12 @@ "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], + "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], + "enhanced-resolve": ["enhanced-resolve@5.18.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ=="], + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + "env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="], @@ -1012,14 +1221,20 @@ "event-target-polyfill": ["event-target-polyfill@0.0.4", "", {}, "sha512-Gs6RLjzlLRdT8X9ZipJdIZI/Y6/HhRLyq9RdDlCsnpxr/+Nn6bU2EFGuC94GjxqhM+Nmij2Vcq98yoHrU8uNFQ=="], + "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], + "eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], + "eventid": ["eventid@2.0.1", "", { "dependencies": { "uuid": "^8.0.0" } }, "sha512-sPNTqiMokAvV048P2c9+foqVJzk49o6d4e0D/sq5jog3pw+4kBgyR0gaM1FM7Mx6Kzd9dztesh9oYz1LWWOpzw=="], + "events-universal": ["events-universal@1.0.1", "", { "dependencies": { "bare-events": "^2.7.0" } }, "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw=="], "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="], "eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="], + "execa": ["execa@9.6.1", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.6", "figures": "^6.1.0", "get-stream": "^9.0.0", "human-signals": "^8.0.1", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^6.0.0", "pretty-ms": "^9.2.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.1.1" } }, "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA=="], + "express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="], "express-rate-limit": ["express-rate-limit@7.5.1", "", { "peerDependencies": { "express": ">= 4.11" } }, "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw=="], @@ -1028,6 +1243,8 @@ "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], + "extract-zip": ["extract-zip@2.0.1", "", { "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" }, "optionalDependencies": { "@types/yauzl": "^2.9.1" }, "bin": { "extract-zip": "cli.js" } }, "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg=="], + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], "fast-diff": ["fast-diff@1.3.0", "", {}, "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="], @@ -1046,12 +1263,16 @@ "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], + "fd-slicer": ["fd-slicer@1.1.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="], + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], "fflate": ["fflate@0.7.4", "", {}, "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw=="], + "figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="], + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], "filelist": ["filelist@1.0.4", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q=="], @@ -1062,6 +1283,8 @@ "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + "find-up-simple": ["find-up-simple@1.0.1", "", {}, "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ=="], + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], @@ -1074,10 +1297,14 @@ "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="], + "form-data-encoder": ["form-data-encoder@4.1.0", "", {}, "sha512-G6NsmEW15s0Uw9XnCg+33H3ViYRyiM0hMrMhhqQOR8NFc5GhYrI+6I3u7OTw7b91J2g8rtvMBZJDbcGb2YUniw=="], + "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], + "forwarded-parse": ["forwarded-parse@2.1.2", "", {}, "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw=="], + "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="], "fs-extra": ["fs-extra@11.3.3", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg=="], @@ -1086,9 +1313,11 @@ "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - "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=="], + "fzf": ["fzf@0.5.2", "", {}, "sha512-Tt4kuxLXFKHy8KT40zwsUPUkg1CrsgY25FxA2U/j/0WgEDCk3ddc/zLTCCcbSHX9FcKtLuVaDGtGE/STWC+j3Q=="], - "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=="], + "gaxios": ["gaxios@6.7.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", "node-fetch": "^2.6.9", "uuid": "^9.0.1" } }, "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ=="], + + "gcp-metadata": ["gcp-metadata@6.1.1", "", { "dependencies": { "gaxios": "^6.1.1", "google-logging-utils": "^0.0.2", "json-bigint": "^1.0.0" } }, "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A=="], "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], @@ -1100,6 +1329,8 @@ "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + "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=="], + "giget": ["giget@2.0.0", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.6.0", "pathe": "^2.0.3" }, "bin": { "giget": "dist/cli.mjs" } }, "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA=="], "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=="], @@ -1112,15 +1343,23 @@ "globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], - "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=="], + "google-auth-library": ["google-auth-library@9.15.1", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^6.1.1", "gcp-metadata": "^6.1.0", "gtoken": "^7.0.0", "jws": "^4.0.0" } }, "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng=="], + + "google-gax": ["google-gax@4.6.1", "", { "dependencies": { "@grpc/grpc-js": "^1.10.9", "@grpc/proto-loader": "^0.7.13", "@types/long": "^4.0.0", "abort-controller": "^3.0.0", "duplexify": "^4.0.0", "google-auth-library": "^9.3.0", "node-fetch": "^2.7.0", "object-hash": "^3.0.0", "proto3-json-serializer": "^2.0.2", "protobufjs": "^7.3.2", "retry-request": "^7.0.0", "uuid": "^9.0.1" } }, "sha512-V6eky/xz2mcKfAd1Ioxyd6nmA61gao3n01C+YeuIwu3vzM9EDR6wcVzMSIbLMDXWeoi9SHYctXuKYC5uJUT3eQ=="], "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], + "googleapis": ["googleapis@137.1.0", "", { "dependencies": { "google-auth-library": "^9.0.0", "googleapis-common": "^7.0.0" } }, "sha512-2L7SzN0FLHyQtFmyIxrcXhgust77067pkkduqkbIpDuj9JzVnByxsRrcRfUMFQam3rQkWW2B0f1i40IwKDWIVQ=="], + + "googleapis-common": ["googleapis-common@7.2.0", "", { "dependencies": { "extend": "^3.0.2", "gaxios": "^6.0.3", "google-auth-library": "^9.7.0", "qs": "^6.7.0", "url-template": "^2.0.8", "uuid": "^9.0.0" } }, "sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA=="], + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + "got": ["got@14.6.6", "", { "dependencies": { "@sindresorhus/is": "^7.0.1", "byte-counter": "^0.1.0", "cacheable-lookup": "^7.0.0", "cacheable-request": "^13.0.12", "decompress-response": "^10.0.0", "form-data-encoder": "^4.0.2", "http2-wrapper": "^2.2.1", "keyv": "^5.5.3", "lowercase-keys": "^3.0.0", "p-cancelable": "^4.0.1", "responselike": "^4.0.2", "type-fest": "^4.26.1" } }, "sha512-QLV1qeYSo5l13mQzWgP/y0LbMr5Plr5fJilgAIwgnwseproEbtNym8xpLsDzeZ6MWXgNE6kdWGBjdh3zT/Qerg=="], + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], - "gtoken": ["gtoken@8.0.0", "", { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw=="], + "gtoken": ["gtoken@7.1.0", "", { "dependencies": { "gaxios": "^6.0.0", "jws": "^4.0.0" } }, "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw=="], "h3": ["h3@2.0.1-rc.5", "", { "dependencies": { "rou3": "^0.7.9", "srvx": "^0.9.1" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"] }, "sha512-qkohAzCab0nLzXNm78tBjZDvtKMTmtygS8BJLT3VPczAQofdqlFXDPkXdLMJN4r05+xqneG8snZJ0HgkERCZTg=="], @@ -1136,10 +1375,26 @@ "hono": ["hono@4.11.3", "", {}, "sha512-PmQi306+M/ct/m5s66Hrg+adPnkD5jiO6IjA7WhWw0gSBSo1EcRegwuI1deZ+wd5pzCGynCcn2DprnE4/yEV4w=="], + "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=="], + + "html-to-text": ["html-to-text@9.0.5", "", { "dependencies": { "@selderee/plugin-htmlparser2": "^0.11.0", "deepmerge": "^4.3.1", "dom-serializer": "^2.0.0", "htmlparser2": "^8.0.2", "selderee": "^0.11.0" } }, "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg=="], + + "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=="], + + "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="], + "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], + "http-proxy-agent": ["http-proxy-agent@5.0.0", "", { "dependencies": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" } }, "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w=="], + + "http2-wrapper": ["http2-wrapper@2.2.1", "", { "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.2.0" } }, "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ=="], + "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], + "human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="], + "iconv-lite": ["iconv-lite@0.7.1", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw=="], "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], @@ -1148,10 +1403,14 @@ "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + "import-in-the-middle": ["import-in-the-middle@1.15.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" } }, "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA=="], + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], + "index-to-position": ["index-to-position@1.2.0", "", {}, "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw=="], + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], "ioredis": ["ioredis@5.8.2", "", { "dependencies": { "@ioredis/commands": "1.4.0", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q=="], @@ -1166,7 +1425,9 @@ "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], - "is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], + "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], + + "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], @@ -1180,8 +1441,14 @@ "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + "is-obj": ["is-obj@2.0.0", "", {}, "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="], + + "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], + "is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="], + "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="], "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], @@ -1246,6 +1513,8 @@ "langsmith": ["langsmith@0.4.2", "", { "dependencies": { "@types/uuid": "^10.0.0", "chalk": "^4.1.2", "console-table-printer": "^2.12.1", "p-queue": "^6.6.2", "semver": "^7.6.3", "uuid": "^10.0.0" }, "peerDependencies": { "@opentelemetry/api": "*", "@opentelemetry/exporter-trace-otlp-proto": "*", "@opentelemetry/sdk-trace-base": "*", "openai": "*" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/exporter-trace-otlp-proto", "@opentelemetry/sdk-trace-base", "openai"] }, "sha512-BvBeFgSmR9esl8x5wsiDlALiHKKPybw2wE2Hh6x1tgSZki46H9c9KI9/06LARbPhyyDu/TZU7exfg6fnhdj1Qg=="], + "leac": ["leac@0.6.0", "", {}, "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg=="], + "leb": ["leb@1.0.0", "", {}, "sha512-Y3c3QZfvKWHX60BVOQPhLCvVGmDYWyJEiINE3drOog6KCyN2AOwvuQQzlS3uJg1J85kzpILXIUwRXULWavir+w=="], "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], @@ -1254,6 +1523,8 @@ "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + "lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="], + "lodash.defaults": ["lodash.defaults@4.2.0", "", {}, "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="], "lodash.isarguments": ["lodash.isarguments@3.1.0", "", {}, "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="], @@ -1262,10 +1533,16 @@ "log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="], + "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], + + "lowercase-keys": ["lowercase-keys@3.0.0", "", {}, "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ=="], + "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + "marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="], + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], "media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="], @@ -1276,6 +1553,8 @@ "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + "mime": ["mime@4.0.7", "", { "bin": { "mime": "bin/cli.js" } }, "sha512-2OfDPL+e03E0LrXaGYOtTFIYhiuzep94NSsuhrNULq+stylcJedcHdzHtz0atMUuGwJfFYs0YL5xeC/Ca2x0eQ=="], + "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], @@ -1284,6 +1563,8 @@ "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], + "mimic-response": ["mimic-response@4.0.0", "", {}, "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg=="], + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], @@ -1292,6 +1573,10 @@ "mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="], + "mnemonist": ["mnemonist@0.40.3", "", { "dependencies": { "obliterator": "^2.0.4" } }, "sha512-Vjyr90sJ23CKKH/qPAgUKicw/v6pRoamxIEDFOF8uSgFME7DqPRpHgRTejWVjkdGg5dXj0/NyxZHZ9bcjH+2uQ=="], + + "module-details-from-path": ["module-details-from-path@1.0.4", "", {}, "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w=="], + "morgan": ["morgan@1.10.1", "", { "dependencies": { "basic-auth": "~2.0.1", "debug": "2.6.9", "depd": "~2.0.0", "on-finished": "~2.3.0", "on-headers": "~1.1.0" } }, "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], @@ -1310,20 +1595,36 @@ "nitro": ["nitro@3.0.1-alpha.1", "", { "dependencies": { "consola": "^3.4.2", "crossws": "^0.4.1", "db0": "^0.3.4", "h3": "2.0.1-rc.5", "jiti": "^2.6.1", "nf3": "^0.1.10", "ofetch": "^2.0.0-alpha.3", "ohash": "^2.0.11", "oxc-minify": "^0.96.0", "oxc-transform": "^0.96.0", "srvx": "^0.9.5", "undici": "^7.16.0", "unenv": "^2.0.0-rc.24", "unstorage": "^2.0.0-alpha.4" }, "peerDependencies": { "rolldown": "*", "rollup": "^4", "vite": "^7", "xml2js": "^0.6.2" }, "optionalPeers": ["rolldown", "rollup", "vite", "xml2js"], "bin": { "nitro": "dist/cli/index.mjs" } }, "sha512-U4AxIsXxdkxzkFrK0XAw0e5Qbojk8jQ50MjjRBtBakC4HurTtQoiZvF+lSe382jhuQZCfAyywGWOFa9QzXLFaw=="], + "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], + "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], - "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=="], + "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], "node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="], + "node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="], + + "node-pty": ["node-pty@1.1.0", "", { "dependencies": { "node-addon-api": "^7.1.0" } }, "sha512-20JqtutY6JPXTUnL0ij1uad7Qe1baT46lyolh2sSENDd4sTzKZ4nmAFkeAARDKwmlLjPx6XKRlwRUxwjOy+lUg=="], + + "normalize-package-data": ["normalize-package-data@6.0.2", "", { "dependencies": { "hosted-git-info": "^7.0.0", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4" } }, "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g=="], + + "normalize-url": ["normalize-url@8.1.1", "", {}, "sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ=="], + + "npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="], + "nuqs": ["nuqs@2.8.6", "", { "dependencies": { "@standard-schema/spec": "1.0.0" }, "peerDependencies": { "@remix-run/react": ">=2", "@tanstack/react-router": "^1", "next": ">=14.2.0", "react": ">=18.2.0 || ^19.0.0-0", "react-router": "^5 || ^6 || ^7", "react-router-dom": "^5 || ^6 || ^7" }, "optionalPeers": ["@remix-run/react", "@tanstack/react-router", "next", "react-router", "react-router-dom"] }, "sha512-aRxeX68b4ULmhio8AADL2be1FWDy0EPqaByPvIYWrA7Pm07UjlrICp/VPlSnXJNAG0+3MQwv3OporO2sOXMVGA=="], "nypm": ["nypm@0.6.2", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.2", "pathe": "^2.0.3", "pkg-types": "^2.3.0", "tinyexec": "^1.0.1" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g=="], "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + "object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], + "obliterator": ["obliterator@2.0.5", "", {}, "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw=="], + "ofetch": ["ofetch@2.0.0-alpha.3", "", {}, "sha512-zpYTCs2byOuft65vI3z43Dd6iSdFbOZZLb9/d21aCpx2rGastVU9dOCv0lu4ykc1Ur1anAYjDi3SUvR0vq50JA=="], "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], @@ -1350,6 +1651,8 @@ "oxc-transform": ["oxc-transform@0.96.0", "", { "optionalDependencies": { "@oxc-transform/binding-android-arm64": "0.96.0", "@oxc-transform/binding-darwin-arm64": "0.96.0", "@oxc-transform/binding-darwin-x64": "0.96.0", "@oxc-transform/binding-freebsd-x64": "0.96.0", "@oxc-transform/binding-linux-arm-gnueabihf": "0.96.0", "@oxc-transform/binding-linux-arm-musleabihf": "0.96.0", "@oxc-transform/binding-linux-arm64-gnu": "0.96.0", "@oxc-transform/binding-linux-arm64-musl": "0.96.0", "@oxc-transform/binding-linux-riscv64-gnu": "0.96.0", "@oxc-transform/binding-linux-s390x-gnu": "0.96.0", "@oxc-transform/binding-linux-x64-gnu": "0.96.0", "@oxc-transform/binding-linux-x64-musl": "0.96.0", "@oxc-transform/binding-wasm32-wasi": "0.96.0", "@oxc-transform/binding-win32-arm64-msvc": "0.96.0", "@oxc-transform/binding-win32-x64-msvc": "0.96.0" } }, "sha512-dQPNIF+gHpSkmC0+Vg9IktNyhcn28Y8R3eTLyzn52UNymkasLicl3sFAtz7oEVuFmCpgGjaUTKkwk+jW2cHpDQ=="], + "p-cancelable": ["p-cancelable@4.0.1", "", {}, "sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg=="], + "p-finally": ["p-finally@1.0.0", "", {}, "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="], "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], @@ -1366,7 +1669,11 @@ "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], - "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], + "parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="], + + "parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="], + + "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=="], @@ -1378,6 +1685,8 @@ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + "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=="], "path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="], @@ -1386,6 +1695,10 @@ "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + "peberminta": ["peberminta@0.9.0", "", {}, "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ=="], + + "pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="], + "perfect-debounce": ["perfect-debounce@2.0.0", "", {}, "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow=="], "pg": ["pg@8.16.3", "", { "dependencies": { "pg-connection-string": "^2.9.1", "pg-pool": "^3.10.1", "pg-protocol": "^1.10.3", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.2.7" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw=="], @@ -1432,10 +1745,20 @@ "prettier-linter-helpers": ["prettier-linter-helpers@1.0.0", "", { "dependencies": { "fast-diff": "^1.1.2" } }, "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w=="], + "pretty-ms": ["pretty-ms@9.3.0", "", { "dependencies": { "parse-ms": "^4.0.0" } }, "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ=="], + + "proto3-json-serializer": ["proto3-json-serializer@2.0.2", "", { "dependencies": { "protobufjs": "^7.2.5" } }, "sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ=="], + + "protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="], + "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="], + + "pumpify": ["pumpify@2.0.1", "", { "dependencies": { "duplexify": "^4.1.1", "inherits": "^2.0.3", "pump": "^3.0.0" } }, "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw=="], + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="], @@ -1446,6 +1769,8 @@ "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + "quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="], + "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], "raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="], @@ -1456,6 +1781,12 @@ "react-dom": ["react-dom@19.2.3", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg=="], + "read-package-up": ["read-package-up@11.0.0", "", { "dependencies": { "find-up-simple": "^1.0.0", "read-pkg": "^9.0.0", "type-fest": "^4.6.0" } }, "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ=="], + + "read-pkg": ["read-pkg@9.0.1", "", { "dependencies": { "@types/normalize-package-data": "^2.4.3", "normalize-package-data": "^6.0.0", "parse-json": "^8.0.0", "type-fest": "^4.6.0", "unicorn-magic": "^0.1.0" } }, "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA=="], + + "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "redis-errors": ["redis-errors@1.2.0", "", {}, "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="], @@ -1468,12 +1799,22 @@ "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + "require-in-the-middle": ["require-in-the-middle@7.5.2", "", { "dependencies": { "debug": "^4.3.5", "module-details-from-path": "^1.0.3", "resolve": "^1.22.8" } }, "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ=="], + + "resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], + + "resolve-alpn": ["resolve-alpn@1.2.1", "", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="], + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + "responselike": ["responselike@4.0.2", "", { "dependencies": { "lowercase-keys": "^3.0.0" } }, "sha512-cGk8IbWEAnaCpdAt1BHzJ3Ahz5ewDJa0KseTsE3qIRMJ3C698W8psM7byCeWVpd/Ha7FUYzuRVzXoKoM6nRUbA=="], + "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.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], + "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=="], "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], @@ -1500,6 +1841,8 @@ "seedrandom": ["seedrandom@3.0.5", "", {}, "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="], + "selderee": ["selderee@0.11.0", "", { "dependencies": { "parseley": "^0.12.0" } }, "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA=="], + "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], "send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="], @@ -1518,6 +1861,8 @@ "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + "shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="], + "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], @@ -1528,12 +1873,22 @@ "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "simple-git": ["simple-git@3.30.0", "", { "dependencies": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", "debug": "^4.4.0" } }, "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg=="], + "simple-wcswidth": ["simple-wcswidth@1.1.2", "", {}, "sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw=="], "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + "spdx-correct": ["spdx-correct@3.2.0", "", { "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA=="], + + "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="], + + "spdx-expression-parse": ["spdx-expression-parse@3.0.1", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q=="], + + "spdx-license-ids": ["spdx-license-ids@3.0.22", "", {}, "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ=="], + "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], "sql-highlight": ["sql-highlight@6.1.0", "", {}, "sha512-ed7OK4e9ywpE7pgRMkMQmZDPKSVdm0oX5IEtZiKnFucSF0zu6c80GZBe38UqHuVhTWJ9xsKgSMjCG2bml86KvA=="], @@ -1546,22 +1901,32 @@ "stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="], + "stream-events": ["stream-events@1.0.5", "", { "dependencies": { "stubs": "^3.0.0" } }, "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg=="], + + "stream-shift": ["stream-shift@1.0.3", "", {}, "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ=="], + "streamx": ["streamx@2.23.0", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg=="], "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + + "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="], + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], "stripe": ["stripe@20.1.2", "", { "dependencies": { "qs": "^6.14.1" }, "peerDependencies": { "@types/node": ">=16" }, "optionalPeers": ["@types/node"] }, "sha512-qU+lQRRJnTxmyvglYBPE24/IepncmywsAg0GDTsTdP2pb+3e3RdREHJZjKgqCmv0phPxN/nmgNPnIPPH8w0P4A=="], "strnum": ["strnum@2.1.2", "", {}, "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ=="], + "stubs": ["stubs@3.0.0", "", {}, "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw=="], + "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="], "superjson": ["superjson@2.2.6", "", { "dependencies": { "copy-anything": "^4" } }, "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA=="], @@ -1570,6 +1935,8 @@ "supports-hyperlinks": ["supports-hyperlinks@4.4.0", "", { "dependencies": { "has-flag": "^5.0.1", "supports-color": "^10.2.2" } }, "sha512-UKbpT93hN5Nr9go5UY7bopIB9YQlMz9nm/ct4IXt/irb5YRkn9WaqrOBJGZ5Pwvsd5FQzSVeYlGdXoCAPQZrPg=="], + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + "swr": ["swr@2.3.8", "", { "dependencies": { "dequal": "^2.0.3", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-gaCPRVoMq8WGDcWj9p4YWzCMPHzE0WNl6W8ADIx9c3JBEIdMkJGMzW+uzXvxHMltwcYACr9jP+32H8/hgwMR7w=="], "synckit": ["synckit@0.11.11", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw=="], @@ -1578,6 +1945,8 @@ "tar-stream": ["tar-stream@3.1.7", "", { "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ=="], + "teeny-request": ["teeny-request@9.0.0", "", { "dependencies": { "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.9", "stream-events": "^1.0.5", "uuid": "^9.0.0" } }, "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g=="], + "terminal-link": ["terminal-link@5.0.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "supports-hyperlinks": "^4.1.0" } }, "sha512-qFAy10MTMwjzjU8U16YS4YoZD+NQLHzLssFMNqgravjbvIPNiqkGFR4yjhJfmY9R5OFU7+yHxc6y+uGHkKwLRA=="], "text-decoder": ["text-decoder@1.2.3", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA=="], @@ -1594,6 +1963,10 @@ "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], + "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + + "tree-sitter-bash": ["tree-sitter-bash@0.25.1", "", { "dependencies": { "node-addon-api": "^8.2.1", "node-gyp-build": "^4.8.2" }, "peerDependencies": { "tree-sitter": "^0.25.0" }, "optionalPeers": ["tree-sitter"] }, "sha512-7hMytuYIMoXOq24yRulgIxthE9YmggZIOHCyPTTuJcu6EU54tYD+4G39cUb28kxC6jMf/AbPfWGLQtgPTdh3xw=="], + "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], @@ -1640,10 +2013,16 @@ "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + "url-template": ["url-template@2.0.8", "", {}, "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw=="], + "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="], + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + "uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "validate-npm-package-license": ["validate-npm-package-license@3.0.4", "", { "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew=="], + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], "watchpack": ["watchpack@2.4.4", "", { "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA=="], @@ -1652,10 +2031,16 @@ "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], + "web-tree-sitter": ["web-tree-sitter@0.25.10", "", { "peerDependencies": { "@types/emscripten": "^1.40.0" }, "optionalPeers": ["@types/emscripten"] }, "sha512-Y09sF44/13XvgVKgO2cNDw5rGk6s26MgoZPXLESvMXeefBf7i6/73eFurre0IsTW6E14Y0ArIzhUMmjoc7xyzA=="], + "webcrypto-core": ["webcrypto-core@1.8.1", "", { "dependencies": { "@peculiar/asn1-schema": "^2.3.13", "@peculiar/json-schema": "^1.1.12", "asn1js": "^3.0.5", "pvtsutils": "^1.3.5", "tslib": "^2.7.0" } }, "sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A=="], + "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + "webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], + "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], "which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="], @@ -1680,6 +2065,8 @@ "xdg-app-paths": ["xdg-app-paths@5.1.0", "", { "dependencies": { "xdg-portable": "^7.0.0" } }, "sha512-RAQ3WkPf4KTU1A8RtFx3gWywzVKe00tfOPFfl2NDGqbIFENQO4kqAJp7mhQjNj/33W5x5hiWWUdyfPq/5SU3QA=="], + "xdg-basedir": ["xdg-basedir@5.1.0", "", {}, "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ=="], + "xdg-portable": ["xdg-portable@7.3.0", "", { "dependencies": { "os-paths": "^4.0.1" } }, "sha512-sqMMuL1rc0FmMBOzCpd0yuy9trqF2yTTVe+E9ogwCSWQCdDEtQUwrZPT6AxqtsFGRNxycgncbP/xmOOSPw5ZUw=="], "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], @@ -1690,8 +2077,12 @@ "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + "yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="], + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="], + "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "zod-to-json-schema": ["zod-to-json-schema@3.25.0", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ=="], @@ -1820,12 +2211,26 @@ "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "@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=="], + "@google-cloud/logging/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], - "@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], + "@google/gemini-cli-core/@google/genai": ["@google/genai@1.30.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.20.1" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-3MRcgczBFbUat1wIlZoLJ0vCCfXgm7Qxjh59cZi2X08RgWLtm9hKOspzp7TOg1TV2e26/MLxR2GR5yD5GmBV2w=="], + + "@google/gemini-cli-core/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], + + "@google/gemini-cli-core/dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="], + + "@google/gemini-cli-core/glob": ["glob@12.0.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-5Qcll1z7IKgHr5g485ePDdHcNQY0k2dtv/bjYy0iuyGxQw2qSOiiXUXJ+AYQpg3HNoUMHqAruX478Jeev7UULw=="], + + "@google/gemini-cli-core/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + + "@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=="], + + "@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=="], "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + "@joshua.litt/get-ripgrep/path-exists": ["path-exists@5.0.0", "", {}, "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ=="], + "@langchain/core/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], "@langchain/core/uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="], @@ -1924,6 +2329,8 @@ "@smithy/util-stream/@smithy/types": ["@smithy/types@4.11.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-mlrmL0DRDVe3mNrjTcVcZEgkFmufITfUAPBEA+AHYiIeYyJebso/He1qLbP3PssRe22KUzLRpQSdBPbXdgZ2VA=="], + "@types/request/form-data": ["form-data@2.5.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.35", "safe-buffer": "^5.2.1" } }, "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A=="], + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], @@ -1966,6 +2373,8 @@ "agents/ai": ["ai@4.3.19", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8", "@ai-sdk/react": "1.2.12", "@ai-sdk/ui-utils": "1.2.11", "@opentelemetry/api": "1.9.0", "jsondiffpatch": "0.6.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.23.8" }, "optionalPeers": ["react"] }, "sha512-dIE2bfNpqHN3r6IINp9znguYdhIOheKW2LDigAMrgt/upT3B8eBGPSCblENvaZGoq+hxaN9fSMzjWpbqloP+7Q=="], + "ai-sdk-provider-gemini-cli/@google/genai": ["@google/genai@1.30.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.20.1" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-3MRcgczBFbUat1wIlZoLJ0vCCfXgm7Qxjh59cZi2X08RgWLtm9hKOspzp7TOg1TV2e26/MLxR2GR5yD5GmBV2w=="], + "ajv-formats/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], @@ -1986,27 +2395,57 @@ "c12/dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="], + "cacheable-request/keyv": ["keyv@5.5.5", "", { "dependencies": { "@keyv/serialize": "^1.1.1" } }, "sha512-FA5LmZVF1VziNc0bIdCSA1IoSVnDCqE8HJIZZv2/W8YmoAM50+tnUgJR/gQZwEeIMleuIOnRnHA/UaZRNeV4iQ=="], + + "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "cosmiconfig/parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], + + "easy-table/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "ecdsa-sig-formatter/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + "eventid/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], + + "execa/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], + "express/cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="], "express/qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="], + "extract-zip/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="], + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "filelist/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], "form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + "gaxios/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + + "gcp-metadata/google-logging-utils": ["google-logging-utils@0.0.2", "", {}, "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ=="], + + "get-stream/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], + "glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "google-gax/@grpc/proto-loader": ["@grpc/proto-loader@0.7.15", "", { "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", "protobufjs": "^7.2.5", "yargs": "^17.7.2" }, "bin": { "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" } }, "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ=="], + + "google-gax/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + + "googleapis-common/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + + "got/keyv": ["keyv@5.5.5", "", { "dependencies": { "@keyv/serialize": "^1.1.1" } }, "sha512-FA5LmZVF1VziNc0bIdCSA1IoSVnDCqE8HJIZZv2/W8YmoAM50+tnUgJR/gQZwEeIMleuIOnRnHA/UaZRNeV4iQ=="], + + "http-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + "iron-session/@types/express": ["@types/express@4.17.25", "", { "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "^1" } }, "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw=="], "iron-session/@types/node": ["@types/node@17.0.45", "", {}, "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="], "iron-session/cookie": ["cookie@0.5.0", "", {}, "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="], - "is-inside-container/is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], + "is-wsl/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], "jsondiffpatch/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], @@ -2034,28 +2473,48 @@ "morgan/on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="], + "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], + + "npm-run-path/unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="], + "nuqs/@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], "ora/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], "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=="], - "ora/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], - "postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "sha.js/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + "string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "string_decoder/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "supports-hyperlinks/has-flag": ["has-flag@5.0.1", "", {}, "sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA=="], "supports-hyperlinks/supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], + "teeny-request/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], + + "teeny-request/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + "terminal-link/ansi-escapes": ["ansi-escapes@7.2.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw=="], "to-buffer/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + "tree-sitter-bash/node-addon-api": ["node-addon-api@8.5.0", "", {}, "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A=="], + "typeorm/reflect-metadata": ["reflect-metadata@0.2.2", "", {}, "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="], + "wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "wsl-utils/is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="], "@ai-sdk/react/@ai-sdk/provider-utils/@ai-sdk/provider": ["@ai-sdk/provider@1.1.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg=="], @@ -2074,9 +2533,23 @@ "@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=="], - "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + "@google/gemini-cli-core/@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=="], + + "@google/gemini-cli-core/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "@google/gemini-cli-core/glob/jackspeak": ["jackspeak@4.1.1", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" } }, "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ=="], + + "@google/gemini-cli-core/glob/minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], - "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + "@google/gemini-cli-core/glob/path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="], + + "@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=="], + + "@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=="], + + "@google/genai/google-auth-library/gtoken": ["gtoken@8.0.0", "", { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw=="], + + "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], @@ -2090,6 +2563,10 @@ "@posthog/agent-toolkit/ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="], + "@types/request/form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "@types/request/form-data/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "@workflow/builders/find-up/locate-path": ["locate-path@7.2.0", "", { "dependencies": { "p-locate": "^6.0.0" } }, "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA=="], @@ -2104,18 +2581,18 @@ "agents/ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.2.8", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA=="], + "ai-sdk-provider-gemini-cli/@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=="], + "ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], "boxen/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], - "boxen/string-width/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], - "boxen/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - "boxen/wrap-ansi/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], - "c12/chokidar/readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], + "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "filelist/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], @@ -2134,21 +2611,43 @@ "ora/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], - "ora/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "teeny-request/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "@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=="], + "@google/gemini-cli-core/@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=="], + + "@google/gemini-cli-core/@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=="], + + "@google/gemini-cli-core/@google/genai/google-auth-library/gtoken": ["gtoken@8.0.0", "", { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw=="], + + "@google/gemini-cli-core/glob/path-scurry/lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], + + "@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=="], + + "@types/request/form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + "@workflow/builders/find-up/locate-path/p-locate": ["p-locate@6.0.0", "", { "dependencies": { "p-limit": "^4.0.0" } }, "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw=="], "@workflow/cli/find-up/locate-path/p-locate": ["p-locate@6.0.0", "", { "dependencies": { "p-limit": "^4.0.0" } }, "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw=="], "agents/ai/@ai-sdk/provider-utils/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - "boxen/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + "ai-sdk-provider-gemini-cli/@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=="], + + "ai-sdk-provider-gemini-cli/@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=="], - "boxen/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + "ai-sdk-provider-gemini-cli/@google/genai/google-auth-library/gtoken": ["gtoken@8.0.0", "", { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw=="], "iron-session/@types/express/@types/express-serve-static-core/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="], @@ -2156,10 +2655,14 @@ "iron-session/@types/express/@types/serve-static/@types/send": ["@types/send@0.17.6", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og=="], + "@google/gemini-cli-core/@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=="], + "@workflow/builders/find-up/locate-path/p-locate/p-limit": ["p-limit@4.0.0", "", { "dependencies": { "yocto-queue": "^1.0.0" } }, "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ=="], "@workflow/cli/find-up/locate-path/p-locate/p-limit": ["p-limit@4.0.0", "", { "dependencies": { "yocto-queue": "^1.0.0" } }, "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ=="], + "ai-sdk-provider-gemini-cli/@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=="], + "@workflow/builders/find-up/locate-path/p-locate/p-limit/yocto-queue": ["yocto-queue@1.2.2", "", {}, "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ=="], "@workflow/cli/find-up/locate-path/p-locate/p-limit/yocto-queue": ["yocto-queue@1.2.2", "", {}, "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ=="], diff --git a/backend/package.json b/backend/package.json index 459a7bb..957540e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -36,6 +36,7 @@ "@vercel/sandbox": "^1.1.1", "@workos-inc/node": "^7.82.0", "ai": "^6.0.0", + "ai-sdk-provider-gemini-cli": "^2.0.1", "axios": "^1.7.9", "cookie-parser": "^1.4.7", "cors": "^2.8.5", diff --git a/backend/src/db/seed.ts b/backend/src/db/seed.ts index dc4a1b5..0b0fb9b 100644 --- a/backend/src/db/seed.ts +++ b/backend/src/db/seed.ts @@ -39,12 +39,6 @@ const PROVIDER_SEEDS: ProviderSeed[] = [ }, ], }, - { - slug: 'kernel', - displayName: 'Kernel.sh', - hasCloudAgent: false, - tools: [{ displayName: 'Browser Automation', slugName: 'kernel/browser' }], - }, { slug: 'cursor', displayName: 'Cursor', diff --git a/backend/src/tools/dynamic.ts b/backend/src/tools/dynamic.ts index fe73125..087278f 100644 --- a/backend/src/tools/dynamic.ts +++ b/backend/src/tools/dynamic.ts @@ -1,8 +1,6 @@ import type { Sandbox } from '@vercel/sandbox'; import { buildQueryRunnerTools, buildInsightTools, buildErrorTools, buildDocumentationTools, type ToolCollection } from './posthog/index'; import { buildCommitTools } from './github/commits'; -import { buildBrowserTools, type SandboxUrl } from './kernel/index'; -import { DEFAULT_BROWSER_PORTS } from '../workflows/helpers/sandbox'; export async function buildDynamicTools(agentId: number, toolSlugs: string[], sandbox: Sandbox): Promise { const tools: ToolCollection = {}; @@ -34,14 +32,5 @@ export async function buildDynamicTools(agentId: number, toolSlugs: string[], sa Object.assign(tools, buildCommitTools(sandbox)); } - if (toolSlugs.includes('kernel/browser')) { - const sandboxUrls: SandboxUrl[] = DEFAULT_BROWSER_PORTS.map((port) => ({ - port, - url: sandbox.domain(port), - })); - const browserTools = buildBrowserTools({ agentId, sandboxUrls }); - Object.assign(tools, browserTools); - } - return tools; } diff --git a/backend/src/tools/kernel/tools/createSession.ts b/backend/src/tools/kernel/tools/createSession.ts index 616e299..cc79e95 100644 --- a/backend/src/tools/kernel/tools/createSession.ts +++ b/backend/src/tools/kernel/tools/createSession.ts @@ -10,7 +10,7 @@ const createSessionSchema = z.object({ function buildDescription(sandboxUrls?: SandboxUrl[]): string { let description = - 'Create a new browser session using Kernel.sh. This starts a remote browser that can be controlled via other browser tools. If you need to access an app running in the sandbox, first start the dev server using runCommand (e.g., "npm run dev &> devserver.log & sleep 2; tail devserver.log") before creating the session.'; + 'Create a new browser session using a browser provider. This starts a remote browser that can be controlled via other browser tools. If you need to access an app running in the sandbox, first start the dev server using runCommand (e.g., "npm run dev &> devserver.log & sleep 2; tail devserver.log") before creating the session.'; if (sandboxUrls && sandboxUrls.length > 0) { description += '\n\nIMPORTANT: The browser runs on an external service and CANNOT access localhost/127.0.0.1. Use these sandbox public URLs instead:'; diff --git a/backend/src/workflows/agent.ts b/backend/src/workflows/agent.ts index 653c285..3e854b5 100644 --- a/backend/src/workflows/agent.ts +++ b/backend/src/workflows/agent.ts @@ -2,6 +2,7 @@ import { Sandbox } from '@vercel/sandbox'; import { AgentStatus } from '../db/entities/Agent'; +import { SubscriptionTier } from '../db/entities/Organization'; import { emitStatus } from '../stream/events'; import { runAgentLLM, runOrchestratorAgentLLM, type TokenUsageAccumulator, AGENT_MODEL, ORCHESTRATOR_MODEL } from './llm'; import { @@ -38,7 +39,7 @@ export async function runOrchestratorAgentWorkflow(payload: AgentJobPayload) { const agent = await loadAgent(payload.agentId); const { repositoryFullName, token } = await validateAndGetToken(agent, payload.repositoryFullName); - sandbox = await prepareSandbox(agent, token, repositoryFullName, payload.baseBranch, payload.toolSlugs); + sandbox = await prepareSandbox(agent, token, repositoryFullName, payload.baseBranch); if (!sandbox) throw new Error('Failed to create sandbox'); sandboxStartTime = Date.now(); @@ -82,7 +83,7 @@ export async function runAgentWorkflow(payload: AgentJobPayload) { const agent = await loadAgent(payload.agentId); const { repositoryFullName, token } = await validateAndGetToken(agent, payload.repositoryFullName); - sandbox = await prepareSandbox(agent, token, repositoryFullName, payload.baseBranch, payload.toolSlugs); + sandbox = await prepareSandbox(agent, token, repositoryFullName, payload.baseBranch); if (!sandbox) throw new Error('Failed to create sandbox'); sandboxStartTime = Date.now(); @@ -93,7 +94,8 @@ export async function runAgentWorkflow(payload: AgentJobPayload) { await Promise.all([emitStatus(agent.id, 'running', 'sandboxagent_starting', 'running AI'), updateAgent(agent, { status: AgentStatus.RUNNING })]); - const response = await runAgentLLM(agent.id, sandbox, payload.toolSlugs || [], previousMessages, usageAccumulator); + const subscriptionTier = agent.workspace.organization?.subscriptionTier ?? SubscriptionTier.FREE; + const response = await runAgentLLM(agent.id, sandbox, payload.toolSlugs || [], previousMessages, usageAccumulator, subscriptionTier); const sandboxDurationMs = Date.now() - sandboxStartTime; await saveAgentResponse(agent, response, usageAccumulator, sandboxDurationMs); diff --git a/backend/src/workflows/helpers/agents.ts b/backend/src/workflows/helpers/agents.ts index 8529260..b1bad09 100644 --- a/backend/src/workflows/helpers/agents.ts +++ b/backend/src/workflows/helpers/agents.ts @@ -11,7 +11,7 @@ import type { BrowserToolResult } from '../../tools/kernel/index'; export async function getAgentById(agentId: number) { return AppDataSource.getRepository(Agent).findOne({ where: { id: agentId }, - relations: ['workspace'], + relations: ['workspace', 'workspace.organization'], }); } diff --git a/backend/src/workflows/llm.ts b/backend/src/workflows/llm.ts index 378e3a6..fd37d12 100644 --- a/backend/src/workflows/llm.ts +++ b/backend/src/workflows/llm.ts @@ -7,12 +7,16 @@ import { Sandbox } from '@vercel/sandbox'; import { PostHog } from 'posthog-node'; import { Agent } from '../db/entities/Agent'; import { Message } from '../db/entities/Message'; +import { SubscriptionTier } from '../db/entities/Organization'; import { sandboxTools } from '../tools/sandboxTools'; import { buildDynamicTools } from '../tools/dynamic'; import { buildOrchestratorAgentTools } from '../tools/primaryAgent'; +import { buildBrowserTools, type SandboxUrl } from '../tools/kernel/index'; +import { DEFAULT_BROWSER_PORTS } from './helpers/sandbox'; import { createReasoningStreamer } from '../stream/events'; import { transformMessagesToModelMessages } from '../utils/llm'; import { AGENT_SYSTEM_PROMPT, ORCHESTRATOR_AGENT_SYSTEM_PROMPT } from './prompts'; +import { createGeminiProvider } from 'ai-sdk-provider-gemini-cli'; if (!process.env.POSTHOG_API_KEY) { throw new Error('POSTHOG_API_KEY is not set'); @@ -32,7 +36,8 @@ export async function runAgentLLM( sandbox: Sandbox, toolSlugs: string[], previousMessages: Message[], - usageAccumulator: TokenUsageAccumulator + usageAccumulator: TokenUsageAccumulator, + subscriptionTier: SubscriptionTier ) { const phClient = new PostHog(process.env.POSTHOG_API_KEY!, { host: 'https://us.i.posthog.com' }); const openaiClient = createOpenAI({ @@ -42,6 +47,16 @@ export async function runAgentLLM( const tools = sandboxTools(agentId, sandbox); const dynamicTools = await buildDynamicTools(agentId, toolSlugs, sandbox); + + // Browser tools are included as base tools for non-free users + const hasBrowserAccess = subscriptionTier !== SubscriptionTier.FREE; + const browserTools = hasBrowserAccess + ? buildBrowserTools({ + agentId, + sandboxUrls: DEFAULT_BROWSER_PORTS.map((port): SandboxUrl => ({ port, url: sandbox.domain(port) })), + }) + : {}; + const messages = transformMessagesToModelMessages(previousMessages); const streamReasoning = createReasoningStreamer(agentId); @@ -55,7 +70,7 @@ export async function runAgentLLM( }, system: AGENT_SYSTEM_PROMPT, messages, - tools: { ...tools, ...dynamicTools }, + tools: { ...tools, ...dynamicTools, ...browserTools }, stopWhen: stepCountIs(32), onStepFinish: (step) => { streamReasoning(step); @@ -99,6 +114,17 @@ export async function runOrchestratorAgentLLM( images: userImages, }); const dynamicTools = await buildDynamicTools(agent.id, toolSlugs, sandbox); + + // Browser tools are included as base tools for non-free users + const subscriptionTier = agent.workspace.organization?.subscriptionTier ?? SubscriptionTier.FREE; + const hasBrowserAccess = subscriptionTier !== SubscriptionTier.FREE; + const browserTools = hasBrowserAccess + ? buildBrowserTools({ + agentId: agent.id, + sandboxUrls: DEFAULT_BROWSER_PORTS.map((port): SandboxUrl => ({ port, url: sandbox.domain(port) })), + }) + : {}; + const messages = transformMessagesToModelMessages(previousMessages); const streamReasoning = createReasoningStreamer(agent.id); @@ -112,7 +138,7 @@ export async function runOrchestratorAgentLLM( }, system: ORCHESTRATOR_AGENT_SYSTEM_PROMPT, messages, - tools: { ...orchestratorAgentTools, ...dynamicTools, ...tools }, + tools: { ...orchestratorAgentTools, ...dynamicTools, ...tools, ...browserTools }, stopWhen: stepCountIs(32), onStepFinish: (step) => { streamReasoning(step); From a48d7176283734b78d35b57629a5d1e6d2481d64 Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Sat, 17 Jan 2026 10:56:08 -0600 Subject: [PATCH 11/14] Automated: create workspace checkpoint (2026-01-17T16:56:08.146Z) --- backend/src/payment/model-pricing.ts | 4 ++ backend/src/workflows/helpers/sandbox.ts | 2 +- backend/src/workflows/llm.ts | 7 ++- backend/src/workflows/steps.ts | 8 ++-- .../pages/Workspace/ToolsContainer.module.css | 25 ++++++++++- .../src/pages/Workspace/ToolsContainer.tsx | 45 ++++++++++++++++--- 6 files changed, 78 insertions(+), 13 deletions(-) diff --git a/backend/src/payment/model-pricing.ts b/backend/src/payment/model-pricing.ts index fa85a33..9f3d6f9 100644 --- a/backend/src/payment/model-pricing.ts +++ b/backend/src/payment/model-pricing.ts @@ -17,6 +17,10 @@ export function getModelPricing(modelName: string): ModelPricing { const pricing = MODEL_PRICING[modelName]; if (!pricing) { + return { + inputMicrodollarsPer1MTokens: 2_000_000, // $2.00 + outputMicrodollarsPer1MTokens: 6_000_000, // $6.00 + }; throw new Error(`Unknown model pricing for "${modelName}"`); } diff --git a/backend/src/workflows/helpers/sandbox.ts b/backend/src/workflows/helpers/sandbox.ts index b9d1e95..70c4429 100644 --- a/backend/src/workflows/helpers/sandbox.ts +++ b/backend/src/workflows/helpers/sandbox.ts @@ -18,7 +18,7 @@ export async function createSandbox(agent: Agent, token: string, repositoryFullN revision: baseBranch, }, runtime: process.env.VERCEL_RUNTIME || 'node22', - timeout: 5 * 60 * 1000, + timeout: 30 * 60 * 1000, resources: { vcpus: 2 }, ports: ports || [], }); diff --git a/backend/src/workflows/llm.ts b/backend/src/workflows/llm.ts index fd37d12..275dfcc 100644 --- a/backend/src/workflows/llm.ts +++ b/backend/src/workflows/llm.ts @@ -28,7 +28,7 @@ export type TokenUsageAccumulator = { totalTokens: number; }; -export const AGENT_MODEL = 'gpt-5-mini'; +export const AGENT_MODEL = 'gpt-5.1-codex'; export const ORCHESTRATOR_MODEL = 'gpt-5-mini'; export async function runAgentLLM( @@ -43,7 +43,10 @@ export async function runAgentLLM( const openaiClient = createOpenAI({ apiKey: process.env.OPENAI_API_KEY, }); + + const geminiClient = createGeminiProvider({ authType: 'oauth-personal' }); const model = withTracing(openaiClient(AGENT_MODEL), phClient, { posthogTraceId: `agent_${agentId}_${previousMessages.length}` }); + const modelGemini = withTracing(geminiClient('gemini-3-pro-preview'), phClient, { posthogTraceId: `agent_${agentId}_${previousMessages.length}` }); const tools = sandboxTools(agentId, sandbox); const dynamicTools = await buildDynamicTools(agentId, toolSlugs, sandbox); @@ -61,7 +64,7 @@ export async function runAgentLLM( const streamReasoning = createReasoningStreamer(agentId); const result = await generateText({ - model, + model: model, providerOptions: { openai: { reasoningEffort: 'high', diff --git a/backend/src/workflows/steps.ts b/backend/src/workflows/steps.ts index f57edbb..55550f8 100644 --- a/backend/src/workflows/steps.ts +++ b/backend/src/workflows/steps.ts @@ -3,6 +3,7 @@ import { Sandbox } from '@vercel/sandbox'; import { Agent, AgentStatus } from '../db/entities/Agent'; import { Message } from '../db/entities/Message'; +import { SubscriptionTier } from '../db/entities/Organization'; import { AppDataSource } from '../db/data-source'; import { emitDone, emitError, emitStatus } from '../stream/events'; import { getAgentById, saveMessage, saveAgentActivity, updateAgent } from './helpers/agents'; @@ -35,11 +36,12 @@ export async function validateAndGetToken(agent: Agent, repositoryFullName: stri return { repositoryFullName: repoName, token }; } -export async function prepareSandbox(agent: Agent, token: string, repositoryFullName: string, baseBranch: string, toolSlugs?: string[]) { +export async function prepareSandbox(agent: Agent, token: string, repositoryFullName: string, baseBranch: string) { await emitStatus(agent.id, 'starting', 'agent_init', 'preparing sandbox'); - // Expose ports if browser tools are enabled - const ports = toolSlugs?.includes('kernel/browser') ? DEFAULT_BROWSER_PORTS : undefined; + // Expose browser ports for non-free users (browser tools are a paid feature) + const hasBrowserAccess = agent.workspace.organization?.subscriptionTier !== SubscriptionTier.FREE; + const ports = hasBrowserAccess ? DEFAULT_BROWSER_PORTS : undefined; try { const sandbox = await createSandbox(agent, token, repositoryFullName, baseBranch, ports); diff --git a/frontend/src/pages/Workspace/ToolsContainer.module.css b/frontend/src/pages/Workspace/ToolsContainer.module.css index 8517218..bdbf6eb 100644 --- a/frontend/src/pages/Workspace/ToolsContainer.module.css +++ b/frontend/src/pages/Workspace/ToolsContainer.module.css @@ -141,10 +141,33 @@ .toolCallHeader { display: flex; justify-content: space-between; - align-items: center; + align-items: flex-start; font-size: 12px; color: var(--color-muted); font-family: monospace; + line-height: 1.6; +} + +.prompt { + color: rgba(255, 255, 255, 0.4); + user-select: none; +} + +.toolName { + color: rgba(255, 255, 255, 0.9); + font-weight: 500; +} + +.toolArgs { + color: rgba(255, 255, 255, 0.5); +} + +.argKey { + color: rgba(147, 197, 253, 0.8); +} + +.argValue { + color: rgba(255, 255, 255, 0.6); } .toolCallResult { diff --git a/frontend/src/pages/Workspace/ToolsContainer.tsx b/frontend/src/pages/Workspace/ToolsContainer.tsx index face09d..fce3529 100644 --- a/frontend/src/pages/Workspace/ToolsContainer.tsx +++ b/frontend/src/pages/Workspace/ToolsContainer.tsx @@ -3,6 +3,23 @@ import style from './ToolsContainer.module.css'; import { BsChevronDown, BsX } from 'react-icons/bs'; import { useState } from 'react'; +function formatToolCommand(toolName: string, args: Record | undefined): string { + if (!args || Object.keys(args).length === 0) { + return toolName; + } + + const formattedArgs = Object.entries(args) + .map(([key, value]) => { + const strValue = typeof value === 'string' ? value : JSON.stringify(value); + // Truncate long values for display + const displayValue = strValue.length > 50 ? strValue.slice(0, 47) + '...' : strValue; + return `--${key} ${displayValue}`; + }) + .join(' '); + + return `${toolName} ${formattedArgs}`; +} + export function ScreenshotImage({ data, mimeType }: { data: string; mimeType: string }) { const [isExpanded, setIsExpanded] = useState(false); @@ -57,7 +74,7 @@ export default function ToolsContainer({

{lastToolCall ? lastToolCall.tool_name !== 'reasoning' - ? `${lastToolCall.tool_name}(${JSON.stringify(lastToolCall.arguments, null, 2)})` + ? formatToolCommand(lastToolCall.tool_name, lastToolCall.arguments) : `${lastToolCall.result}` : 'Setting up sandbox...'}

@@ -77,11 +94,27 @@ export default function ToolsContainer({ {toolCalls.map((toolCall) => (
- - {toolCall.tool_name !== 'reasoning' && Codee-Sandbox % } - {toolCall.tool_name !== 'reasoning' && - `${toolCall.tool_name}(${toolCall.arguments && Object.keys(toolCall.arguments).length > 0 && JSON.stringify(toolCall.arguments)})`} - + {toolCall.tool_name !== 'reasoning' && ( + + ${' '} + {toolCall.tool_name} + {toolCall.arguments && Object.keys(toolCall.arguments).length > 0 && ( + + {Object.entries(toolCall.arguments).map(([key, value], i) => { + const strValue = typeof value === 'string' ? value : JSON.stringify(value); + const displayValue = strValue.length > 60 ? strValue.slice(0, 57) + '...' : strValue; + return ( + + {' '} + --{key}{' '} + {displayValue} + + ); + })} + + )} + + )}
{toolCall.result && (
From 403d1e2e730bb1b0e98292082759fde030f9e077 Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Sun, 18 Jan 2026 18:53:56 -0600 Subject: [PATCH 12/14] improve UI --- frontend/src/pages/Usage/UsageCard.tsx | 5 +- .../pages/Workspace/ToolsContainer.module.css | 4 +- .../src/pages/Workspace/ToolsContainer.tsx | 95 +++++++++---------- 3 files changed, 48 insertions(+), 56 deletions(-) diff --git a/frontend/src/pages/Usage/UsageCard.tsx b/frontend/src/pages/Usage/UsageCard.tsx index 4354c4c..0018608 100644 --- a/frontend/src/pages/Usage/UsageCard.tsx +++ b/frontend/src/pages/Usage/UsageCard.tsx @@ -17,10 +17,7 @@ export default function UsageCard({ title, usedValue, limitValue, percentUsed }:
-
+
{percentUsed}% used diff --git a/frontend/src/pages/Workspace/ToolsContainer.module.css b/frontend/src/pages/Workspace/ToolsContainer.module.css index bdbf6eb..df55508 100644 --- a/frontend/src/pages/Workspace/ToolsContainer.module.css +++ b/frontend/src/pages/Workspace/ToolsContainer.module.css @@ -194,7 +194,9 @@ border-radius: 6px; border: 1px solid rgba(255, 255, 255, 0.1); cursor: pointer; - transition: transform 0.15s ease, border-color 0.15s ease; + transition: + transform 0.15s ease, + border-color 0.15s ease; object-fit: contain; background: rgba(0, 0, 0, 0.3); } diff --git a/frontend/src/pages/Workspace/ToolsContainer.tsx b/frontend/src/pages/Workspace/ToolsContainer.tsx index fce3529..861aad6 100644 --- a/frontend/src/pages/Workspace/ToolsContainer.tsx +++ b/frontend/src/pages/Workspace/ToolsContainer.tsx @@ -7,7 +7,7 @@ function formatToolCommand(toolName: string, args: Record | und if (!args || Object.keys(args).length === 0) { return toolName; } - + const formattedArgs = Object.entries(args) .map(([key, value]) => { const strValue = typeof value === 'string' ? value : JSON.stringify(value); @@ -16,7 +16,7 @@ function formatToolCommand(toolName: string, args: Record | und return `--${key} ${displayValue}`; }) .join(' '); - + return `${toolName} ${formattedArgs}`; } @@ -25,20 +25,11 @@ export function ScreenshotImage({ data, mimeType }: { data: string; mimeType: st return ( <> - Screenshot setIsExpanded(true)} - /> + Screenshot setIsExpanded(true)} /> {isExpanded && (
setIsExpanded(false)}>
- Screenshot (full size) + Screenshot (full size)
)} @@ -57,8 +48,10 @@ export default function ToolsContainer({ setShowFullContent: (showFullContent: boolean) => void; isThinking: boolean; }) { + const visibleToolCalls = toolCalls.filter((toolCall) => !(toolCall.tool_name === 'reasoning' && toolCall.result === '[REDACTED]')); + if (!showFullContent) { - const lastToolCall = toolCalls[toolCalls.length - 1]; + const lastToolCall = visibleToolCalls[visibleToolCalls.length - 1]; return (
setShowFullContent(true)}> @@ -91,45 +84,45 @@ export default function ToolsContainer({
- {toolCalls.map((toolCall) => ( -
-
- {toolCall.tool_name !== 'reasoning' && ( - - ${' '} - {toolCall.tool_name} - {toolCall.arguments && Object.keys(toolCall.arguments).length > 0 && ( - - {Object.entries(toolCall.arguments).map(([key, value], i) => { - const strValue = typeof value === 'string' ? value : JSON.stringify(value); - const displayValue = strValue.length > 60 ? strValue.slice(0, 57) + '...' : strValue; - return ( - - {' '} - --{key}{' '} - {displayValue} - - ); - })} - - )} - + {toolCalls.map((toolCall) => + toolCall.tool_name === 'reasoning' && toolCall.result === '[REDACTED]' ? null : ( +
+
+ {toolCall.tool_name !== 'reasoning' && ( + + $ {toolCall.tool_name} + {toolCall.arguments && Object.keys(toolCall.arguments).length > 0 && ( + + {Object.entries(toolCall.arguments).map(([key, value], i) => { + const strValue = typeof value === 'string' ? value : JSON.stringify(value); + const displayValue = strValue.length > 60 ? strValue.slice(0, 57) + '...' : strValue; + return ( + + {' '} + --{key} {displayValue} + + ); + })} + + )} + + )} +
+ {toolCall.result && ( +
+ {typeof toolCall.result === 'object' ? JSON.stringify(toolCall.result, null, 2) : toolCall.result} +
+ )} + {toolCall.images && toolCall.images.length > 0 && ( +
+ {toolCall.images.map((image, index) => ( + + ))} +
)}
- {toolCall.result && ( -
- {typeof toolCall.result === 'object' ? JSON.stringify(toolCall.result, null, 2) : toolCall.result} -
- )} - {toolCall.images && toolCall.images.length > 0 && ( -
- {toolCall.images.map((image, index) => ( - - ))} -
- )} -
- ))} + ) + )}
); } From 565df09bad00d92a343a733f44e6b240f0cc7d48 Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Sat, 24 Jan 2026 16:07:43 -0600 Subject: [PATCH 13/14] migrate to durable agent --- backend/bun.lock | 53 +- backend/package.json | 3 + backend/src/tools/kernel/tools/screenshot.ts | 5 +- backend/src/utils/llm.ts | 14 +- backend/src/workflows/llm.ts | 50 +- backend/src/workflows/prompts.ts | 3 + frontend/package-lock.json | 3323 ++++++++++++++++++ 7 files changed, 3411 insertions(+), 40 deletions(-) create mode 100644 frontend/package-lock.json diff --git a/backend/bun.lock b/backend/bun.lock index 646c7d2..6fda7a2 100644 --- a/backend/bun.lock +++ b/backend/bun.lock @@ -5,14 +5,17 @@ "": { "name": "backend", "dependencies": { + "@ai-sdk/google": "^3.0.10", "@ai-sdk/openai": "^3.0.0", "@onkernel/ai-sdk": "^0.0.3", "@onkernel/sdk": "^0.25.0", + "@openrouter/ai-sdk-provider": "^1.5.4", "@posthog/agent-toolkit": "^0.2.4", "@posthog/ai": "^7.3.0", "@trpc/server": "^11.0.0-rc.553", "@types/bcryptjs": "^3.0.0", "@vercel/sandbox": "^1.1.1", + "@workflow/ai": "^4.0.1-beta.51", "@workos-inc/node": "^7.82.0", "ai": "^6.0.0", "ai-sdk-provider-gemini-cli": "^2.0.1", @@ -51,18 +54,26 @@ }, }, "packages": { + "@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "3.0.5", "@ai-sdk/provider-utils": "4.0.9" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-mu9djDW2kiJS/ihH5BwGy2c/zwSlcTjx1NWPvY/Ug12SWToqzozSyd1EIXRlfXyfwzL2CWrqMNyybqi9OVDXgg=="], + "@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.4", "", { "dependencies": { "@ai-sdk/provider": "3.0.1", "@ai-sdk/provider-utils": "4.0.2", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OlccjNYZ5+4FaNyvs0kb3N5H6U/QCKlKPTGsgUo8IZkqfMQu8ALI1XD6l/BCuTKto+OO9xUPObT/W7JhbqJ5nA=="], + "@ai-sdk/google": ["@ai-sdk/google@3.0.10", "", { "dependencies": { "@ai-sdk/provider": "3.0.4", "@ai-sdk/provider-utils": "4.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-qd2EM9SlD7wWFrq036hwKsuAgkCVxQbwJzctszdmzPs9yUZg795/gHtZRpKItZhbyHSNWhAHmJwEgKjD+HOzuQ=="], + "@ai-sdk/openai": ["@ai-sdk/openai@3.0.2", "", { "dependencies": { "@ai-sdk/provider": "3.0.1", "@ai-sdk/provider-utils": "4.0.2" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-GONwavgSWtcWO+t9+GpGK8l7nIYh+zNtCL/NYDSeHxHiw6ksQS9XMRWrZyE5NpJ0EXNxSAWCHIDmb1WvTqhq9Q=="], - "@ai-sdk/provider": ["@ai-sdk/provider@3.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-2lR4w7mr9XrydzxBSjir4N6YMGdXD+Np1Sh0RXABh7tWdNFFwIeRI1Q+SaYZMbfL8Pg8RRLcrxQm51yxTLhokg=="], + "@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.18", "", { "dependencies": { "@ai-sdk/provider": "3.0.5", "@ai-sdk/provider-utils": "4.0.9" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-CMbsSDWzQT5y0woUWRqom+eUDsyB+btFyA68MGkrUOBWDDsmcCWt/DHUAAIWC5GO+hwcX4WXT2Q9KJQrQJ9RQg=="], + + "@ai-sdk/provider": ["@ai-sdk/provider@3.0.4", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-5KXyBOSEX+l67elrEa+wqo/LSsSTtrPj9Uoh3zMbe/ceQX4ucHI3b9nUEfNkGF3Ry1svv90widAt+aiKdIJasQ=="], - "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.2", "", { "dependencies": { "@ai-sdk/provider": "3.0.1", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-KaykkuRBdF/ffpI5bwpL4aSCmO/99p8/ci+VeHwJO8tmvXtiVAb99QeyvvvXmL61e9Zrvv4GBGoajW19xdjkVQ=="], + "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.8", "", { "dependencies": { "@ai-sdk/provider": "3.0.4", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ns9gN7MmpI8vTRandzgz+KK/zNMLzhrriiKECMt4euLtQFSBgNfydtagPOX4j4pS1/3KvHF6RivhT3gNQgBZsg=="], "@ai-sdk/react": ["@ai-sdk/react@1.2.12", "", { "dependencies": { "@ai-sdk/provider-utils": "2.2.8", "@ai-sdk/ui-utils": "1.2.11", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.23.8" }, "optionalPeers": ["zod"] }, "sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g=="], "@ai-sdk/ui-utils": ["@ai-sdk/ui-utils@1.2.11", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w=="], + "@ai-sdk/xai": ["@ai-sdk/xai@3.0.33", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.18", "@ai-sdk/provider": "3.0.5", "@ai-sdk/provider-utils": "4.0.9" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ilhzN7KVB1aT8hk64HdrL5lYwOxQ2i1d38zX0gHc/KcibVK/4zY6Z6UGvvvdJ6mHFFtt0nbhvCkNS6FkV7990g=="], + "@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.71.2", "", { "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-TGNDEUuEstk/DKu0/TflXAEt+p+p/WhTlFzEnoosvbaDU2LTjm42igSdlL0VijrKpWejtOKxX0b8A7uc+XiSAQ=="], "@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=="], @@ -391,6 +402,10 @@ "@onkernel/sdk": ["@onkernel/sdk@0.25.0", "", {}, "sha512-kMZ/499V9KCksvI/IxYx8juBKViWaCBLsoCOaZdfvLuXBy15310V+yoNUqu+J5q4Yfh+rHBcpFxn9H+GHfHfOQ=="], + "@openrouter/ai-sdk-provider": ["@openrouter/ai-sdk-provider@1.5.4", "", { "dependencies": { "@openrouter/sdk": "^0.1.27" }, "peerDependencies": { "ai": "^5.0.0", "zod": "^3.24.1 || ^v4" } }, "sha512-xrSQPUIH8n9zuyYZR0XK7Ba0h2KsjJcMkxnwaYfmv13pKs3sDkjPzVPPhlhzqBGddHb5cFEwJ9VFuFeDcxCDSw=="], + + "@openrouter/sdk": ["@openrouter/sdk@0.1.27", "", { "dependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-RH//L10bSmc81q25zAZudiI4kNkLgxF2E+WU42vghp3N6TEvZ6F0jK7uT3tOxkEn91gzmMw9YVmDENy7SJsajQ=="], + "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], "@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.203.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ=="], @@ -843,6 +858,8 @@ "@vercel/sandbox": ["@vercel/sandbox@1.1.1", "", { "dependencies": { "@vercel/oidc": "^3.0.5", "async-retry": "1.3.3", "jsonlines": "0.1.1", "ms": "2.1.3", "tar-stream": "3.1.7", "undici": "^7.16.0", "zod": "3.24.4" } }, "sha512-/VczVmqS07TmRGMU2mZkuTGdLSabJkI4APVBFdc2coK2UtmKumKrAPwb339NgPWPN13i6lMKPFJx7PHR81mpjA=="], + "@workflow/ai": ["@workflow/ai@4.0.1-beta.51", "", { "dependencies": { "@ai-sdk/provider": "^2.0.0 || ^3.0.0", "zod": "4.1.11" }, "optionalDependencies": { "@ai-sdk/anthropic": "^2.0.0 || ^3.0.0", "@ai-sdk/gateway": "^2.0.0 || ^3.0.0", "@ai-sdk/google": "^2.0.0 || ^3.0.0", "@ai-sdk/openai": "^2.0.0 || ^3.0.0", "@ai-sdk/xai": "^2.0.0 || ^3.0.0" }, "peerDependencies": { "ai": "^5 || ^6", "workflow": "4.0.1-beta.50" } }, "sha512-YMcLEng+ZActD2Uu/njCsQXMLZ5CrGslXDVoFFoBTbskda6LAgxdxp1h6GcuaCCEBxcaFU35051bzILYcO8nXg=="], + "@workflow/astro": ["@workflow/astro@4.0.0-beta.19", "", { "dependencies": { "@swc/core": "1.15.3", "@workflow/builders": "4.0.1-beta.36", "@workflow/rollup": "4.0.0-beta.6", "@workflow/swc-plugin": "4.0.1-beta.12", "@workflow/vite": "4.0.0-beta.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-O5ZN4axqdz7TByGr89cP+plTyhuXHd7pk4Y+UX0WSJRYVowOd1Vc4frVjCPPkPXScwigD8jBvJiTZ5cYlkh3bA=="], "@workflow/builders": ["@workflow/builders@4.0.1-beta.36", "", { "dependencies": { "@swc/core": "1.15.3", "@workflow/core": "4.0.1-beta.36", "@workflow/errors": "4.0.1-beta.13", "@workflow/swc-plugin": "4.0.1-beta.12", "builtin-modules": "5.0.0", "chalk": "5.6.2", "enhanced-resolve": "5.18.2", "esbuild": "^0.25.11", "find-up": "7.0.0", "tinyglobby": "0.2.14" } }, "sha512-6LV0CdqBA8uA+eYRx4icvuK699wAO4G432LGHlUSkC8299jd/GXhkoLryY9ubMgpseYV2409ufJ5q4YAHsDKpg=="], @@ -2089,12 +2106,32 @@ "zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], + "@ai-sdk/anthropic/@ai-sdk/provider": ["@ai-sdk/provider@3.0.5", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-2Xmoq6DBJqmSl80U6V9z5jJSJP7ehaJJQMy2iFUqTay06wdCqTnPVBBQbtEL8RCChenL+q5DC5H5WzU3vV3v8w=="], + + "@ai-sdk/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.9", "", { "dependencies": { "@ai-sdk/provider": "3.0.5", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bB4r6nfhBOpmoS9mePxjRoCy+LnzP3AfhyMGCkGL4Mn9clVNlqEeKj26zEKEtB6yoSVcT1IQ0Zh9fytwMCDnow=="], + + "@ai-sdk/gateway/@ai-sdk/provider": ["@ai-sdk/provider@3.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-2lR4w7mr9XrydzxBSjir4N6YMGdXD+Np1Sh0RXABh7tWdNFFwIeRI1Q+SaYZMbfL8Pg8RRLcrxQm51yxTLhokg=="], + + "@ai-sdk/gateway/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.2", "", { "dependencies": { "@ai-sdk/provider": "3.0.1", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-KaykkuRBdF/ffpI5bwpL4aSCmO/99p8/ci+VeHwJO8tmvXtiVAb99QeyvvvXmL61e9Zrvv4GBGoajW19xdjkVQ=="], + + "@ai-sdk/openai/@ai-sdk/provider": ["@ai-sdk/provider@3.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-2lR4w7mr9XrydzxBSjir4N6YMGdXD+Np1Sh0RXABh7tWdNFFwIeRI1Q+SaYZMbfL8Pg8RRLcrxQm51yxTLhokg=="], + + "@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.2", "", { "dependencies": { "@ai-sdk/provider": "3.0.1", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-KaykkuRBdF/ffpI5bwpL4aSCmO/99p8/ci+VeHwJO8tmvXtiVAb99QeyvvvXmL61e9Zrvv4GBGoajW19xdjkVQ=="], + + "@ai-sdk/openai-compatible/@ai-sdk/provider": ["@ai-sdk/provider@3.0.5", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-2Xmoq6DBJqmSl80U6V9z5jJSJP7ehaJJQMy2iFUqTay06wdCqTnPVBBQbtEL8RCChenL+q5DC5H5WzU3vV3v8w=="], + + "@ai-sdk/openai-compatible/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.9", "", { "dependencies": { "@ai-sdk/provider": "3.0.5", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bB4r6nfhBOpmoS9mePxjRoCy+LnzP3AfhyMGCkGL4Mn9clVNlqEeKj26zEKEtB6yoSVcT1IQ0Zh9fytwMCDnow=="], + "@ai-sdk/react/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.2.8", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA=="], "@ai-sdk/ui-utils/@ai-sdk/provider": ["@ai-sdk/provider@1.1.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg=="], "@ai-sdk/ui-utils/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.2.8", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA=="], + "@ai-sdk/xai/@ai-sdk/provider": ["@ai-sdk/provider@3.0.5", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-2Xmoq6DBJqmSl80U6V9z5jJSJP7ehaJJQMy2iFUqTay06wdCqTnPVBBQbtEL8RCChenL+q5DC5H5WzU3vV3v8w=="], + + "@ai-sdk/xai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.9", "", { "dependencies": { "@ai-sdk/provider": "3.0.5", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bB4r6nfhBOpmoS9mePxjRoCy+LnzP3AfhyMGCkGL4Mn9clVNlqEeKj26zEKEtB6yoSVcT1IQ0Zh9fytwMCDnow=="], + "@aws-crypto/sha256-browser/@aws-sdk/types": ["@aws-sdk/types@3.965.0", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-jvodoJdMavvg8faN7co58vVJRO5MVep4JFPRzUNCzpJ98BDqWDk/ad045aMJcmxkLzYLS2UAnUmqjJ/tUPNlzQ=="], "@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=="], @@ -2261,6 +2298,8 @@ "@onkernel/ai-sdk/zod": ["zod@4.2.1", "", {}, "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw=="], + "@openrouter/sdk/zod": ["zod@4.2.1", "", {}, "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw=="], + "@posthog/agent-toolkit/ai": ["ai@5.0.116", "", { "dependencies": { "@ai-sdk/gateway": "2.0.23", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-+2hYJ80/NcDWuv9K2/MLP3cTCFgwWHmHlS1tOpFUKKcmLbErAAlE/S2knsKboc3PNAu8pQkDr2N3K/Vle7ENgQ=="], "@posthog/ai/zod": ["zod@4.2.1", "", {}, "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw=="], @@ -2343,6 +2382,8 @@ "@vercel/sandbox/zod": ["zod@3.24.4", "", {}, "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg=="], + "@workflow/ai/zod": ["zod@4.1.11", "", {}, "sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg=="], + "@workflow/builders/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], "@workflow/builders/find-up": ["find-up@7.0.0", "", { "dependencies": { "locate-path": "^7.2.0", "path-exists": "^5.0.0", "unicorn-magic": "^0.1.0" } }, "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g=="], @@ -2373,6 +2414,14 @@ "agents/ai": ["ai@4.3.19", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8", "@ai-sdk/react": "1.2.12", "@ai-sdk/ui-utils": "1.2.11", "@opentelemetry/api": "1.9.0", "jsondiffpatch": "0.6.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.23.8" }, "optionalPeers": ["react"] }, "sha512-dIE2bfNpqHN3r6IINp9znguYdhIOheKW2LDigAMrgt/upT3B8eBGPSCblENvaZGoq+hxaN9fSMzjWpbqloP+7Q=="], + "ai/@ai-sdk/provider": ["@ai-sdk/provider@3.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-2lR4w7mr9XrydzxBSjir4N6YMGdXD+Np1Sh0RXABh7tWdNFFwIeRI1Q+SaYZMbfL8Pg8RRLcrxQm51yxTLhokg=="], + + "ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.2", "", { "dependencies": { "@ai-sdk/provider": "3.0.1", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-KaykkuRBdF/ffpI5bwpL4aSCmO/99p8/ci+VeHwJO8tmvXtiVAb99QeyvvvXmL61e9Zrvv4GBGoajW19xdjkVQ=="], + + "ai-sdk-provider-gemini-cli/@ai-sdk/provider": ["@ai-sdk/provider@3.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-2lR4w7mr9XrydzxBSjir4N6YMGdXD+Np1Sh0RXABh7tWdNFFwIeRI1Q+SaYZMbfL8Pg8RRLcrxQm51yxTLhokg=="], + + "ai-sdk-provider-gemini-cli/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.2", "", { "dependencies": { "@ai-sdk/provider": "3.0.1", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-KaykkuRBdF/ffpI5bwpL4aSCmO/99p8/ci+VeHwJO8tmvXtiVAb99QeyvvvXmL61e9Zrvv4GBGoajW19xdjkVQ=="], + "ai-sdk-provider-gemini-cli/@google/genai": ["@google/genai@1.30.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.20.1" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-3MRcgczBFbUat1wIlZoLJ0vCCfXgm7Qxjh59cZi2X08RgWLtm9hKOspzp7TOg1TV2e26/MLxR2GR5yD5GmBV2w=="], "ajv-formats/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], diff --git a/backend/package.json b/backend/package.json index 957540e..56b97d4 100644 --- a/backend/package.json +++ b/backend/package.json @@ -26,14 +26,17 @@ "typescript-eslint": "^8.50.1" }, "dependencies": { + "@ai-sdk/google": "^3.0.10", "@ai-sdk/openai": "^3.0.0", "@onkernel/ai-sdk": "^0.0.3", "@onkernel/sdk": "^0.25.0", + "@openrouter/ai-sdk-provider": "^1.5.4", "@posthog/agent-toolkit": "^0.2.4", "@posthog/ai": "^7.3.0", "@trpc/server": "^11.0.0-rc.553", "@types/bcryptjs": "^3.0.0", "@vercel/sandbox": "^1.1.1", + "@workflow/ai": "^4.0.1-beta.51", "@workos-inc/node": "^7.82.0", "ai": "^6.0.0", "ai-sdk-provider-gemini-cli": "^2.0.1", diff --git a/backend/src/tools/kernel/tools/screenshot.ts b/backend/src/tools/kernel/tools/screenshot.ts index bb05012..f04e951 100644 --- a/backend/src/tools/kernel/tools/screenshot.ts +++ b/backend/src/tools/kernel/tools/screenshot.ts @@ -37,7 +37,10 @@ export function buildScreenshotTool(params: { agentId: number }) { mimeType: 'image/png', }; - await emitStatus(agentId, 'running', 'tool_browser_screenshot', 'Screenshot captured', { arguments: {} }); + await emitStatus(agentId, 'running', 'tool_browser_screenshot', 'Screenshot captured', { + arguments: {}, + images: [image], + }); return { text: 'Screenshot captured successfully.', diff --git a/backend/src/utils/llm.ts b/backend/src/utils/llm.ts index 88fa93f..0cbb56e 100644 --- a/backend/src/utils/llm.ts +++ b/backend/src/utils/llm.ts @@ -1,16 +1,11 @@ import { generateObject, type ModelMessage, type ToolCallPart, type ToolResultPart } from 'ai'; -import { createOpenAI } from '@ai-sdk/openai'; +import { google } from '@ai-sdk/google'; import { z } from 'zod'; import type { Message } from '../db/entities/Message'; import type { ToolCall } from '../db/entities/ToolCall'; -// import { getPostHog } from './posthog'; - -const openaiClient = createOpenAI({ - apiKey: process.env.OPENAI_API_KEY, -}); export async function generateTitle(prompt: string): Promise { - const model = openaiClient('gpt-5-nano'); + const model = google('gemini-2.5-flash-lite'); // const posthog = getPostHog(); setup posthog later if I want to bother w/ distinct id tracking try { @@ -18,11 +13,6 @@ export async function generateTitle(prompt: string): Promise { model, system: 'You are Codee, an async coding agent. Generate a concise workspace title under 7 words. Avoid filler like quotes or exclamations.', prompt, - providerOptions: { - openai: { - reasoningEffort: 'minimal', - }, - }, schema: z.object({ title: z .string() diff --git a/backend/src/workflows/llm.ts b/backend/src/workflows/llm.ts index 275dfcc..22b8532 100644 --- a/backend/src/workflows/llm.ts +++ b/backend/src/workflows/llm.ts @@ -1,6 +1,6 @@ 'use step'; -import { generateText, stepCountIs } from 'ai'; +import { ToolLoopAgent, stepCountIs } from 'ai'; import { createOpenAI } from '@ai-sdk/openai'; import { withTracing } from '@posthog/ai'; import { Sandbox } from '@vercel/sandbox'; @@ -16,7 +16,8 @@ import { DEFAULT_BROWSER_PORTS } from './helpers/sandbox'; import { createReasoningStreamer } from '../stream/events'; import { transformMessagesToModelMessages } from '../utils/llm'; import { AGENT_SYSTEM_PROMPT, ORCHESTRATOR_AGENT_SYSTEM_PROMPT } from './prompts'; -import { createGeminiProvider } from 'ai-sdk-provider-gemini-cli'; +import { google } from '@ai-sdk/google'; +import { createOpenRouter } from '@openrouter/ai-sdk-provider'; if (!process.env.POSTHOG_API_KEY) { throw new Error('POSTHOG_API_KEY is not set'); @@ -28,7 +29,7 @@ export type TokenUsageAccumulator = { totalTokens: number; }; -export const AGENT_MODEL = 'gpt-5.1-codex'; +export const AGENT_MODEL = 'gemini-2.5-flash-lite'; export const ORCHESTRATOR_MODEL = 'gpt-5-mini'; export async function runAgentLLM( @@ -40,14 +41,10 @@ export async function runAgentLLM( subscriptionTier: SubscriptionTier ) { const phClient = new PostHog(process.env.POSTHOG_API_KEY!, { host: 'https://us.i.posthog.com' }); - const openaiClient = createOpenAI({ - apiKey: process.env.OPENAI_API_KEY, + const modelGoogle = withTracing(google('gemini-2.5-pro'), phClient, { + posthogTraceId: `agent_${agentId}_${previousMessages.length}`, }); - const geminiClient = createGeminiProvider({ authType: 'oauth-personal' }); - const model = withTracing(openaiClient(AGENT_MODEL), phClient, { posthogTraceId: `agent_${agentId}_${previousMessages.length}` }); - const modelGemini = withTracing(geminiClient('gemini-3-pro-preview'), phClient, { posthogTraceId: `agent_${agentId}_${previousMessages.length}` }); - const tools = sandboxTools(agentId, sandbox); const dynamicTools = await buildDynamicTools(agentId, toolSlugs, sandbox); @@ -63,16 +60,9 @@ export async function runAgentLLM( const messages = transformMessagesToModelMessages(previousMessages); const streamReasoning = createReasoningStreamer(agentId); - const result = await generateText({ - model: model, - providerOptions: { - openai: { - reasoningEffort: 'high', - reasoningSummary: 'detailed', - }, - }, - system: AGENT_SYSTEM_PROMPT, - messages, + const agent = new ToolLoopAgent({ + model: modelGoogle, + instructions: AGENT_SYSTEM_PROMPT, tools: { ...tools, ...dynamicTools, ...browserTools }, stopWhen: stepCountIs(32), onStepFinish: (step) => { @@ -81,10 +71,17 @@ export async function runAgentLLM( usageAccumulator.completionTokens += step.usage.outputTokens || 0; usageAccumulator.totalTokens += step.usage.totalTokens || 0; }, + maxRetries: 10, }); + const result = await agent.generate({ messages }); + + console.log('token usage', result.usage); + await phClient.shutdown(); + console.log('result', result.text); + return { final: result.text, steps: result.steps, @@ -103,7 +100,9 @@ export async function runOrchestratorAgentLLM( const openaiClient = createOpenAI({ apiKey: process.env.OPENAI_API_KEY, }); - const model = withTracing(openaiClient(ORCHESTRATOR_MODEL), phClient, { posthogTraceId: `agent_${agent.id}_${previousMessages.length}` }); + const model = withTracing(openaiClient(ORCHESTRATOR_MODEL), phClient, { + posthogTraceId: `agent_${agent.id}_${previousMessages.length}`, + }); const tools = sandboxTools(agent.id, sandbox); const userImages = previousMessages.filter((message) => message.sender === 'USER').flatMap((message) => message.images); @@ -131,18 +130,17 @@ export async function runOrchestratorAgentLLM( const messages = transformMessagesToModelMessages(previousMessages); const streamReasoning = createReasoningStreamer(agent.id); - const result = await generateText({ + const orchestratorAgent = new ToolLoopAgent({ model, + instructions: ORCHESTRATOR_AGENT_SYSTEM_PROMPT, + tools: { ...orchestratorAgentTools, ...dynamicTools, ...tools, ...browserTools }, + stopWhen: stepCountIs(32), providerOptions: { openai: { reasoningEffort: 'high', reasoningSummary: 'concise', }, }, - system: ORCHESTRATOR_AGENT_SYSTEM_PROMPT, - messages, - tools: { ...orchestratorAgentTools, ...dynamicTools, ...tools, ...browserTools }, - stopWhen: stepCountIs(32), onStepFinish: (step) => { streamReasoning(step); usageAccumulator.promptTokens += step.usage.inputTokens || 0; @@ -151,6 +149,8 @@ export async function runOrchestratorAgentLLM( }, }); + const result = await orchestratorAgent.generate({ messages }); + await phClient.shutdown(); return { diff --git a/backend/src/workflows/prompts.ts b/backend/src/workflows/prompts.ts index a84834e..eb80274 100644 --- a/backend/src/workflows/prompts.ts +++ b/backend/src/workflows/prompts.ts @@ -39,6 +39,9 @@ This will render them in a row for easy comparison. Furthermore, when prompted with any change that will result in a modification to an existing component/page/etc on the frontend, take a before and after screenshot to show the user the difference. +Do NOT respond to the user without images, especially when you yourself are taking screenshots. + +Do NOT use markdown for any response. The UI does NOT support markdown. `; export const ORCHESTRATOR_AGENT_SYSTEM_PROMPT = ` diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000..a163266 --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,3323 @@ +{ + "name": "frontend", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "frontend", + "version": "0.0.0", + "dependencies": { + "@tanstack/react-query": "^5.90.12", + "@trpc/client": "^11.0.0-rc.553", + "@trpc/react-query": "^11.8.1", + "axios": "^1.13.2", + "date-fns": "^4.1.0", + "eslint-plugin-react-refresh": "^0.4.26", + "react": "^19.1.1", + "react-dom": "^19.1.1", + "react-grab": "^0.0.91", + "react-icons": "^5.5.0", + "react-router-dom": "^7.9.5", + "superjson": "^2.2.1" + }, + "devDependencies": { + "@eslint/js": "^9.36.0", + "@types/axios": "^0.9.36", + "@types/bun": "^1.3.5", + "@types/node": "^24.6.0", + "@types/react": "^19.1.16", + "@types/react-dom": "^19.1.9", + "@vitejs/plugin-react": "^4.3.4", + "eslint": "^9.36.0", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-prettier": "^5.5.4", + "eslint-plugin-react-hooks": "^5.2.0", + "globals": "^16.4.0", + "prettier": "^3.7.4", + "typescript": "5.9.3", + "typescript-eslint": "^8.45.0", + "vite": "^6.0.7" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.5", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.2", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.54.0.tgz", + "integrity": "sha512-OywsdRHrFvCdvsewAInDKCNyR3laPA2mc9bRYJ6LBp5IyvF3fvXbbNR0bSzHlZVFtn6E0xw2oZlyjg4rKCVcng==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.54.0.tgz", + "integrity": "sha512-Skx39Uv+u7H224Af+bDgNinitlmHyQX1K/atIA32JP3JQw6hVODX5tkbi2zof/E69M1qH2UoN3Xdxgs90mmNYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.54.0", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.54.0.tgz", + "integrity": "sha512-cOo7biqwkpawslEfox5Vs8/qj83M/aZCSSNIWpVzfU2CYHa2G3P1UN5WF01RdTHSgCkri7XOlTdtk17BezlV3A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.54.0.tgz", + "integrity": "sha512-miSvuFkmvFbgJ1BevMa4CPCFt5MPGw094knM64W9I0giUIMMmRYcGW/JWZDriaw/k1kOBtsWh1z6nIFV1vPNtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.54.0.tgz", + "integrity": "sha512-KGXIs55+b/ZfZsq9aR026tmr/+7tq6VG6MsnrvF4H8VhwflTIuYh+LFUlIsRdQSgrgmtM3fVATzEAj4hBQlaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.54.0.tgz", + "integrity": "sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.54.0.tgz", + "integrity": "sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.54.0.tgz", + "integrity": "sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.54.0.tgz", + "integrity": "sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.54.0.tgz", + "integrity": "sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.54.0.tgz", + "integrity": "sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.54.0.tgz", + "integrity": "sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.54.0.tgz", + "integrity": "sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.54.0.tgz", + "integrity": "sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.54.0.tgz", + "integrity": "sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.54.0.tgz", + "integrity": "sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.54.0.tgz", + "integrity": "sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.54.0.tgz", + "integrity": "sha512-c2V0W1bsKIKfbLMBu/WGBz6Yci8nJ/ZJdheE0EwB73N3MvHYKiKGs3mVilX4Gs70eGeDaMqEob25Tw2Gb9Nqyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.54.0.tgz", + "integrity": "sha512-woEHgqQqDCkAzrDhvDipnSirm5vxUXtSKDYTVpZG3nUdW/VVB5VdCYA2iReSj/u3yCZzXID4kuKG7OynPnB3WQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.54.0.tgz", + "integrity": "sha512-dzAc53LOuFvHwbCEOS0rPbXp6SIhAf2txMP5p6mGyOXXw5mWY8NGGbPMPrs4P1WItkfApDathBj/NzMLUZ9rtQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.54.0.tgz", + "integrity": "sha512-hYT5d3YNdSh3mbCU1gwQyPgQd3T2ne0A3KG8KSBdav5TiBg6eInVmV+TeR5uHufiIgSFg0XsOWGW5/RhNcSvPg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tanstack/query-core": { + "version": "5.90.12", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.90.12", + "license": "MIT", + "peer": true, + "dependencies": { + "@tanstack/query-core": "5.90.12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, + "node_modules/@trpc/client": { + "version": "11.8.1", + "funding": [ + "https://trpc.io/sponsor" + ], + "license": "MIT", + "peer": true, + "peerDependencies": { + "@trpc/server": "11.8.1", + "typescript": ">=5.7.2" + } + }, + "node_modules/@trpc/react-query": { + "version": "11.8.1", + "funding": [ + "https://trpc.io/sponsor" + ], + "license": "MIT", + "peerDependencies": { + "@tanstack/react-query": "^5.80.3", + "@trpc/client": "11.8.1", + "@trpc/server": "11.8.1", + "react": ">=18.2.0", + "react-dom": ">=18.2.0", + "typescript": ">=5.7.2" + } + }, + "node_modules/@trpc/server": { + "version": "11.8.1", + "funding": [ + "https://trpc.io/sponsor" + ], + "license": "MIT", + "peer": true, + "peerDependencies": { + "typescript": ">=5.7.2" + } + }, + "node_modules/@types/axios": { + "version": "0.9.36", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/bun": { + "version": "1.3.5", + "dev": true, + "license": "MIT", + "dependencies": { + "bun-types": "1.3.5" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.10.4", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.7", + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/react-reconciler": { + "version": "0.28.9", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.50.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.50.1", + "@typescript-eslint/type-utils": "8.50.1", + "@typescript-eslint/utils": "8.50.1", + "@typescript-eslint/visitor-keys": "8.50.1", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.50.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.50.1", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.50.1", + "@typescript-eslint/types": "8.50.1", + "@typescript-eslint/typescript-estree": "8.50.1", + "@typescript-eslint/visitor-keys": "8.50.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.50.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.50.1", + "@typescript-eslint/types": "^8.50.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.50.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.50.1", + "@typescript-eslint/visitor-keys": "8.50.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.50.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.50.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.50.1", + "@typescript-eslint/typescript-estree": "8.50.1", + "@typescript-eslint/utils": "8.50.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.50.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.50.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.50.1", + "@typescript-eslint/tsconfig-utils": "8.50.1", + "@typescript-eslint/types": "8.50.1", + "@typescript-eslint/visitor-keys": "8.50.1", + "debug": "^4.3.4", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch/node_modules/brace-expansion": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.3", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.50.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.50.1", + "@typescript-eslint/types": "8.50.1", + "@typescript-eslint/typescript-estree": "8.50.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.50.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.50.1", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "license": "Python-2.0" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.2", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.11", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/bippy": { + "version": "0.5.27", + "license": "MIT", + "dependencies": { + "@types/react-reconciler": "^0.28.9" + }, + "peerDependencies": { + "react": ">=17.0.1" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bun-types": { + "version": "1.3.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001761", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.1.1", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/copy-anything": { + "version": "4.0.5", + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "license": "MIT" + }, + "node_modules/date-fns": { + "version": "4.1.0", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.267", + "dev": true, + "license": "ISC" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.2", + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.4", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.11.7" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.26", + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "16.5.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-what": { + "version": "5.5.0", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "dev": true, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.7.4", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "19.2.3", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.3", + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.3" + } + }, + "node_modules/react-grab": { + "version": "0.0.91", + "license": "MIT", + "dependencies": { + "bippy": "^0.5.26", + "solid-js": "^1.9.10" + }, + "bin": { + "react-grab": "dist/cli.cjs" + } + }, + "node_modules/react-icons": { + "version": "5.5.0", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "7.11.0", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.11.0", + "license": "MIT", + "dependencies": { + "react-router": "7.11.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/rollup": { + "version": "4.54.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.54.0", + "@rollup/rollup-android-arm64": "4.54.0", + "@rollup/rollup-darwin-arm64": "4.54.0", + "@rollup/rollup-darwin-x64": "4.54.0", + "@rollup/rollup-freebsd-arm64": "4.54.0", + "@rollup/rollup-freebsd-x64": "4.54.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.54.0", + "@rollup/rollup-linux-arm-musleabihf": "4.54.0", + "@rollup/rollup-linux-arm64-gnu": "4.54.0", + "@rollup/rollup-linux-arm64-musl": "4.54.0", + "@rollup/rollup-linux-loong64-gnu": "4.54.0", + "@rollup/rollup-linux-ppc64-gnu": "4.54.0", + "@rollup/rollup-linux-riscv64-gnu": "4.54.0", + "@rollup/rollup-linux-riscv64-musl": "4.54.0", + "@rollup/rollup-linux-s390x-gnu": "4.54.0", + "@rollup/rollup-linux-x64-gnu": "4.54.0", + "@rollup/rollup-linux-x64-musl": "4.54.0", + "@rollup/rollup-openharmony-arm64": "4.54.0", + "@rollup/rollup-win32-arm64-msvc": "4.54.0", + "@rollup/rollup-win32-ia32-msvc": "4.54.0", + "@rollup/rollup-win32-x64-gnu": "4.54.0", + "@rollup/rollup-win32-x64-msvc": "4.54.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/seroval": { + "version": "1.3.2", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/seroval-plugins": { + "version": "1.3.3", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "seroval": "^1.0" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/solid-js": { + "version": "1.9.10", + "license": "MIT", + "dependencies": { + "csstype": "^3.1.0", + "seroval": "~1.3.0", + "seroval-plugins": "~1.3.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/superjson": { + "version": "2.2.6", + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/synckit": { + "version": "0.11.11", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/ts-api-utils": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.50.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.50.1", + "@typescript-eslint/parser": "8.50.1", + "@typescript-eslint/typescript-estree": "8.50.1", + "@typescript-eslint/utils": "8.50.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "dev": true, + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "6.4.1", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} From 5a168ccf3590a6074ea169fe526691d831ff59bd Mon Sep 17 00:00:00 2001 From: Brandon Pieczka <134565367+Bardemic@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:00:48 -0600 Subject: [PATCH 14/14] truncated outputs + environments --- backend/src/db/data-source.ts | 2 + backend/src/db/entities/Agent.ts | 10 + backend/src/db/entities/Environment.ts | 40 +++ backend/src/providers/base.ts | 1 + backend/src/providers/codee.ts | 3 + backend/src/providers/cursor.ts | 1 + backend/src/providers/index.ts | 2 + backend/src/providers/jules.ts | 1 + backend/src/tools/sandboxTools.ts | 72 ++++- backend/src/trpc/router.ts | 2 + backend/src/trpc/routers/environments.ts | 130 ++++++++ backend/src/trpc/routers/workspace.ts | 3 + backend/src/utils/llm.ts | 2 +- backend/src/workflows/agent.ts | 10 +- backend/src/workflows/llm.ts | 20 +- backend/src/workflows/prompts.ts | 19 +- backend/src/workflows/steps.ts | 64 +++- frontend/src/App.tsx | 2 + frontend/src/components/Sidebar/Sidebar.tsx | 3 +- frontend/src/lib/types.ts | 2 + .../src/pages/Environments/Environments.tsx | 60 ++++ .../components/CreateEnvironmentModal.tsx | 290 ++++++++++++++++++ .../Environments/components/styles.module.css | 285 +++++++++++++++++ .../Environments/environments.module.css | 104 +++++++ frontend/src/pages/Home/Home.tsx | 13 +- .../src/pages/Home/components/ChatBox.tsx | 21 +- .../Home/components/EnvironmentSelector.tsx | 69 +++++ .../src/pages/Workspace/ToolsContainer.tsx | 2 +- frontend/src/pages/Workspace/Workspace.tsx | 40 ++- 29 files changed, 1228 insertions(+), 45 deletions(-) create mode 100644 backend/src/db/entities/Environment.ts create mode 100644 backend/src/trpc/routers/environments.ts create mode 100644 frontend/src/pages/Environments/Environments.tsx create mode 100644 frontend/src/pages/Environments/components/CreateEnvironmentModal.tsx create mode 100644 frontend/src/pages/Environments/components/styles.module.css create mode 100644 frontend/src/pages/Environments/environments.module.css create mode 100644 frontend/src/pages/Home/components/EnvironmentSelector.tsx diff --git a/backend/src/db/data-source.ts b/backend/src/db/data-source.ts index d6ee457..abc12e0 100644 --- a/backend/src/db/data-source.ts +++ b/backend/src/db/data-source.ts @@ -14,6 +14,7 @@ import { WorkspaceTool } from './entities/WorkspaceTool'; import { WorkerDefinitionTool } from './entities/WorkerDefinitionTool'; import { seedDefaults } from './seed'; import { SlackUserMapping } from './entities/SlackUserMapping'; +import { Environment } from './entities/Environment'; const { PGHOST = 'localhost', @@ -39,6 +40,7 @@ export const AppDataSource = new DataSource({ synchronize: NODE_ENV !== 'production', entities: [ Agent, + Environment, IntegrationConnection, IntegrationProvider, Message, diff --git a/backend/src/db/entities/Agent.ts b/backend/src/db/entities/Agent.ts index bf74ba7..1a4dabb 100644 --- a/backend/src/db/entities/Agent.ts +++ b/backend/src/db/entities/Agent.ts @@ -1,6 +1,7 @@ import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, Index, OneToMany, CreateDateColumn, UpdateDateColumn } from 'typeorm'; import type { Workspace } from './Workspace'; import type { Message } from './Message'; +import type { Environment } from './Environment'; export enum AgentStatus { PENDING = 'PENDING', @@ -53,6 +54,15 @@ export class Agent { @Column({ type: 'boolean', default: false }) isOrchestratorAgent!: boolean; + @Column({ nullable: true }) + environmentId!: number | null; + + @ManyToOne('Environment', { + onDelete: 'SET NULL', + nullable: true, + }) + environment!: Environment | null; + @CreateDateColumn({ default: 'now()' }) createdAt!: Date; diff --git a/backend/src/db/entities/Environment.ts b/backend/src/db/entities/Environment.ts new file mode 100644 index 0000000..531d38a --- /dev/null +++ b/backend/src/db/entities/Environment.ts @@ -0,0 +1,40 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, Index, ManyToOne } from 'typeorm'; +import type { Organization } from './Organization'; + +export interface EnvironmentFile { + path: string; + content: string; +} + +@Entity() +@Index(['name', 'organizationId'], { unique: true }) +export class Environment { + @PrimaryGeneratedColumn() + id!: number; + + @Column({ length: 200 }) + name!: string; + + @Column() + organizationId!: number; + + @ManyToOne('Organization', { + onDelete: 'CASCADE', + }) + organization!: Organization; + + @Column({ length: 500 }) + githubRepositoryName!: string; + + @Column({ type: 'text', nullable: true }) + description!: string | null; + + @Column({ type: 'jsonb', default: [] }) + files!: EnvironmentFile[]; + + @CreateDateColumn() + createdAt!: Date; + + @UpdateDateColumn() + updatedAt!: Date; +} diff --git a/backend/src/providers/base.ts b/backend/src/providers/base.ts index 91f2f95..9051bd1 100644 --- a/backend/src/providers/base.ts +++ b/backend/src/providers/base.ts @@ -34,6 +34,7 @@ export interface CloudProvider { model?: string | null; isOrchestratorAgent: boolean; images: MessageImage[]; + environmentId?: number | null; }): Promise; getMessages(agent: Agent): Promise; sendMessage(agent: Agent, message: string, images: MessageImage[]): Promise; diff --git a/backend/src/providers/codee.ts b/backend/src/providers/codee.ts index 454b6a3..c6845f8 100644 --- a/backend/src/providers/codee.ts +++ b/backend/src/providers/codee.ts @@ -21,6 +21,7 @@ export class CodeeProvider implements CloudProvider { model, isOrchestratorAgent, images, + environmentId, }: { organizationId: number; workspace: Workspace; @@ -31,6 +32,7 @@ export class CodeeProvider implements CloudProvider { model?: string | null; isOrchestratorAgent: boolean; images: MessageImage[]; + environmentId?: number | null; }): Promise { const agentRepository = AppDataSource.getRepository(Agent); const messageRepository = AppDataSource.getRepository(Message); @@ -43,6 +45,7 @@ export class CodeeProvider implements CloudProvider { name: `Codee Agent${model ? ` (${model})` : ''}`, model: model || null, isOrchestratorAgent, + environmentId: environmentId || null, }); await agentRepository.save(agent); agent.url = `http://localhost:5173/agent/${agent.id}`; diff --git a/backend/src/providers/cursor.ts b/backend/src/providers/cursor.ts index 6bacba8..3e85fd8 100644 --- a/backend/src/providers/cursor.ts +++ b/backend/src/providers/cursor.ts @@ -27,6 +27,7 @@ export class CursorProvider implements CloudProvider { baseBranch: string; model?: string | null; images: MessageImage[]; + environmentId?: number | null; }): Promise { const agentRepository = AppDataSource.getRepository(Agent); const agent = agentRepository.create({ diff --git a/backend/src/providers/index.ts b/backend/src/providers/index.ts index 1a96db6..ff095db 100644 --- a/backend/src/providers/index.ts +++ b/backend/src/providers/index.ts @@ -26,6 +26,7 @@ export async function createAgentsFromProviders(params: { branchName: string; cloudProviders: CloudProviderConfig[]; images: MessageImage[]; + environmentId?: number | null; }): Promise { let first: Agent | null = null; for (const config of params.cloudProviders) { @@ -43,6 +44,7 @@ export async function createAgentsFromProviders(params: { model: agentConfig.model, isOrchestratorAgent: false, images: params.images, + environmentId: params.environmentId, }); if (!first) first = agent; } diff --git a/backend/src/providers/jules.ts b/backend/src/providers/jules.ts index 2ed9c4b..afd81aa 100644 --- a/backend/src/providers/jules.ts +++ b/backend/src/providers/jules.ts @@ -28,6 +28,7 @@ export class JulesProvider implements CloudProvider { model?: string | null; isOrchestratorAgent: boolean; images: MessageImage[]; + environmentId?: number | null; }): Promise { const agentRepository = AppDataSource.getRepository(Agent); const agent = agentRepository.create({ diff --git a/backend/src/tools/sandboxTools.ts b/backend/src/tools/sandboxTools.ts index 561c149..48dd7bb 100644 --- a/backend/src/tools/sandboxTools.ts +++ b/backend/src/tools/sandboxTools.ts @@ -3,6 +3,22 @@ import { tool, zodSchema } from 'ai'; import type { Sandbox } from '@vercel/sandbox'; import { emitStatus } from '../stream/events'; +const COMMAND_TIMEOUT_MS = 30 * 1000; // 30 seconds +const MAX_OUTPUT_LINES = 200; +const DEFAULT_FILE_LINES = 200; + +function truncateOutput(output: string): string { + const lines = output.split('\n'); + const totalLines = lines.length; + + if (totalLines <= MAX_OUTPUT_LINES) { + return output; + } + + const truncated = lines.slice(0, MAX_OUTPUT_LINES).join('\n'); + return `${truncated}\n\n...[showing ${MAX_OUTPUT_LINES} of ${totalLines} lines]`; +} + async function streamToString(stream: NodeJS.ReadableStream): Promise { const chunks: Buffer[] = []; for await (const chunk of stream) { @@ -18,6 +34,8 @@ export function sandboxTools(agentId: number, sandbox: Sandbox) { const readFileInputSchema = z.object({ relativeFilePath: z.string().describe('Relative file path to read'), + startLine: z.number().optional().default(1).describe('Line to start from (1-indexed)'), + limit: z.number().optional().default(DEFAULT_FILE_LINES).describe('Max lines to return'), }); const updateFileInputSchema = z.object({ @@ -48,14 +66,31 @@ export function sandboxTools(agentId: number, sandbox: Sandbox) { }); const readFile = tool({ - description: 'Read a file from the repository', + description: 'Read a file from the repository. Returns paginated content - use startLine and limit for large files.', inputSchema: zodSchema(readFileInputSchema), execute: async (input) => { - const { relativeFilePath } = input; + const { relativeFilePath, startLine, limit } = input; const stream = await sandbox.readFile({ path: relativeFilePath }); - const content = stream ? await streamToString(stream) : ''; - await emitStatus(agentId, 'running', 'tool_read_file', content, { arguments: input }); - return content; + const fullContent = stream ? await streamToString(stream) : ''; + const lines = fullContent.split('\n'); + const totalLines = lines.length; + + const slice = lines.slice(startLine - 1, startLine - 1 + limit); + const endLine = Math.min(startLine + slice.length - 1, totalLines); + const hasMore = startLine + limit <= totalLines; + + // Add line numbers to each line + const numberedContent = slice.map((line, i) => `${startLine + i}: ${line}`).join('\n'); + + let result: string; + if (hasMore) { + result = `${numberedContent}\n\n...[showing lines ${startLine}-${endLine} of ${totalLines}]`; + } else { + result = numberedContent; + } + + await emitStatus(agentId, 'running', 'tool_read_file', result, { arguments: input }); + return result; }, }); @@ -71,16 +106,29 @@ export function sandboxTools(agentId: number, sandbox: Sandbox) { }); const runCommand = tool({ - description: 'Run a shell command in the sandbox', + description: 'Run a shell command in the sandbox. Output is truncated to 200 lines - use head/tail or redirect to file for full output.', inputSchema: zodSchema(runCommandInputSchema), execute: async (input) => { const { command } = input; - const result = await sandbox.runCommand({ - cmd: 'bash', - args: ['-c', command], - }); - await emitStatus(agentId, 'running', 'tool_run_command', await result.stdout(), { arguments: input }); - return result.stdout(); + try { + const result = await sandbox.runCommand({ + cmd: 'bash', + args: ['-c', command], + signal: AbortSignal.timeout(COMMAND_TIMEOUT_MS), + }); + const stdout = await result.stdout(); + const truncatedOutput = truncateOutput(stdout); + await emitStatus(agentId, 'running', 'tool_run_command', truncatedOutput, { arguments: input }); + return truncatedOutput; + } catch (error: unknown) { + const isTimeout = error instanceof DOMException && (error.name === 'TimeoutError' || error.name === 'AbortError'); + if (isTimeout) { + const message = `Command timed out after ${COMMAND_TIMEOUT_MS / 1000}s. The command likely starts a long-running process (e.g. a dev server). Use background execution instead: "command &> output.log & sleep 2; tail output.log"`; + await emitStatus(agentId, 'running', 'tool_run_command', message, { arguments: input }); + return message; + } + throw error; + } }, }); diff --git a/backend/src/trpc/router.ts b/backend/src/trpc/router.ts index 96ad826..29ad7e9 100644 --- a/backend/src/trpc/router.ts +++ b/backend/src/trpc/router.ts @@ -4,8 +4,10 @@ import { workersRouter } from './routers/workers'; import { workspaceRouter } from './routers/workspace'; import { organizationRouter } from './routers/organization'; import { paymentRouter } from './routers/payment'; +import { environmentsRouter } from './routers/environments'; export const appRouter = router({ + environments: environmentsRouter, integrations: integrationsRouter, workers: workersRouter, workspace: workspaceRouter, diff --git a/backend/src/trpc/routers/environments.ts b/backend/src/trpc/routers/environments.ts new file mode 100644 index 0000000..b334c70 --- /dev/null +++ b/backend/src/trpc/routers/environments.ts @@ -0,0 +1,130 @@ +import { TRPCError } from '@trpc/server'; +import { z } from 'zod'; +import { authedProcedure, router } from '../trpc'; +import { AppDataSource } from '../../db/data-source'; +import { Environment } from '../../db/entities/Environment'; + +const envFileSchema = z.object({ + path: z.string().min(1), + content: z.string(), +}); + +const environmentInput = z.object({ + name: z.string().min(1).max(200), + github_repository_name: z.string().min(1), + description: z.string().optional(), + files: z.array(envFileSchema).min(1), +}); + +export const environmentsRouter = router({ + list: authedProcedure.query(async ({ ctx }) => { + const environments = await AppDataSource.getRepository(Environment).find({ + where: { organizationId: ctx.organization.id }, + order: { id: 'DESC' }, + }); + + return environments.map((env) => ({ + id: env.id, + name: env.name, + github_repository_name: env.githubRepositoryName, + description: env.description, + files_count: env.files?.length || 0, + file_paths: (env.files || []).map((f) => f.path), + })); + }), + + get: authedProcedure.input(z.object({ id: z.number() })).query(async ({ ctx, input }) => { + const environment = await AppDataSource.getRepository(Environment).findOne({ + where: { id: input.id, organizationId: ctx.organization.id }, + }); + if (!environment) throw new TRPCError({ code: 'NOT_FOUND' }); + + return { + id: environment.id, + name: environment.name, + github_repository_name: environment.githubRepositoryName, + description: environment.description, + created_at: environment.createdAt, + updated_at: environment.updatedAt, + files: environment.files || [], + }; + }), + + listByRepository: authedProcedure.input(z.object({ github_repository_name: z.string() })).query(async ({ ctx, input }) => { + const environments = await AppDataSource.getRepository(Environment).find({ + where: { + organizationId: ctx.organization.id, + githubRepositoryName: input.github_repository_name, + }, + order: { name: 'ASC' }, + }); + + return environments.map((env) => ({ + id: env.id, + name: env.name, + github_repository_name: env.githubRepositoryName, + description: env.description, + files_count: env.files?.length || 0, + })); + }), + + create: authedProcedure.input(environmentInput).mutation(async ({ ctx, input }) => { + const environmentRepository = AppDataSource.getRepository(Environment); + const existing = await environmentRepository.findOne({ + where: { name: input.name, organizationId: ctx.organization.id }, + }); + if (existing) { + throw new TRPCError({ + code: 'CONFLICT', + message: 'Environment name already used', + }); + } + + const environment = environmentRepository.create({ + name: input.name, + organizationId: ctx.organization.id, + githubRepositoryName: input.github_repository_name, + description: input.description || null, + files: input.files, + }); + await environmentRepository.save(environment); + + return { id: environment.id }; + }), + + update: authedProcedure.input(environmentInput.extend({ id: z.number() })).mutation(async ({ ctx, input }) => { + const environmentRepository = AppDataSource.getRepository(Environment); + const environment = await environmentRepository.findOne({ + where: { id: input.id, organizationId: ctx.organization.id }, + }); + if (!environment) throw new TRPCError({ code: 'NOT_FOUND' }); + + const duplicate = await environmentRepository.findOne({ + where: { name: input.name, organizationId: ctx.organization.id }, + }); + if (duplicate && duplicate.id !== environment.id) { + throw new TRPCError({ + code: 'CONFLICT', + message: 'Environment name already used', + }); + } + + environment.name = input.name; + environment.githubRepositoryName = input.github_repository_name; + environment.description = input.description || null; + environment.files = input.files; + await environmentRepository.save(environment); + + return { ok: true }; + }), + + delete: authedProcedure.input(z.object({ id: z.number() })).mutation(async ({ ctx, input }) => { + const environmentRepository = AppDataSource.getRepository(Environment); + const environment = await environmentRepository.findOne({ + where: { id: input.id, organizationId: ctx.organization.id }, + }); + if (!environment) throw new TRPCError({ code: 'NOT_FOUND' }); + await environmentRepository.remove(environment); + return { ok: true }; + }), +}); diff --git a/backend/src/trpc/routers/workspace.ts b/backend/src/trpc/routers/workspace.ts index bc52f69..e23855f 100644 --- a/backend/src/trpc/routers/workspace.ts +++ b/backend/src/trpc/routers/workspace.ts @@ -76,6 +76,7 @@ export const workspaceRouter = router({ branch_name: z.string().min(1), sub_agents: z.boolean(), images: z.array(imageSchema).default([]), + environment_id: z.number().optional(), }) ) .mutation(async ({ ctx, input }) => { @@ -134,6 +135,7 @@ export const workspaceRouter = router({ branchName: input.branch_name, cloudProviders: input.cloud_providers, images: input.images, + environmentId: input.environment_id, }); return { agent_id: firstAgent.id }; @@ -147,6 +149,7 @@ export const workspaceRouter = router({ baseBranch: input.branch_name, isOrchestratorAgent: true, images: input.images, + environmentId: input.environment_id, }); return { agent_id: orchestratorAgent.id }; diff --git a/backend/src/utils/llm.ts b/backend/src/utils/llm.ts index 0cbb56e..9f8ddc9 100644 --- a/backend/src/utils/llm.ts +++ b/backend/src/utils/llm.ts @@ -56,7 +56,7 @@ export function transformMessagesToModelMessages(previousMessages: Message[]): M } } else { // Agent messages - include tool calls if present - const toolCalls = message.toolCalls || []; + const toolCalls = (message.toolCalls || []).filter((toolCall) => toolCall.toolName !== 'reasoning'); if (toolCalls.length > 0) { // Build assistant message with tool calls diff --git a/backend/src/workflows/agent.ts b/backend/src/workflows/agent.ts index 3e854b5..dc09c44 100644 --- a/backend/src/workflows/agent.ts +++ b/backend/src/workflows/agent.ts @@ -16,6 +16,7 @@ import { cleanupSandbox, markAgentComplete, markAgentFailed, + writeEnvironmentFiles, } from './steps'; import { updateAgent } from './helpers/agents'; @@ -44,6 +45,9 @@ export async function runOrchestratorAgentWorkflow(payload: AgentJobPayload) { sandboxStartTime = Date.now(); + // Write environment files if configured + await writeEnvironmentFiles(agent, sandbox); + const previousMessages = await loadPreviousMessages(payload.agentId); await Promise.all([ @@ -78,6 +82,7 @@ export async function runAgentWorkflow(payload: AgentJobPayload) { let sandbox: Sandbox | undefined; const usageAccumulator: TokenUsageAccumulator = { promptTokens: 0, completionTokens: 0, totalTokens: 0 }; let sandboxStartTime = 0; + let environmentFilePaths: string[] = []; try { const agent = await loadAgent(payload.agentId); @@ -90,6 +95,9 @@ export async function runAgentWorkflow(payload: AgentJobPayload) { await createBranchIfNeeded(agent, sandbox, payload.isOrchestratorAgent); + // Write environment files if configured + environmentFilePaths = await writeEnvironmentFiles(agent, sandbox); + const previousMessages = await loadPreviousMessages(payload.agentId); await Promise.all([emitStatus(agent.id, 'running', 'sandboxagent_starting', 'running AI'), updateAgent(agent, { status: AgentStatus.RUNNING })]); @@ -106,7 +114,7 @@ export async function runAgentWorkflow(payload: AgentJobPayload) { return; } - await commitChangesIfNeeded(sandbox, agent.id, payload.prompt); + await commitChangesIfNeeded(sandbox, agent.id, payload.prompt, environmentFilePaths); await cleanupSandbox(sandbox, agent.id); diff --git a/backend/src/workflows/llm.ts b/backend/src/workflows/llm.ts index 22b8532..e9b1c27 100644 --- a/backend/src/workflows/llm.ts +++ b/backend/src/workflows/llm.ts @@ -41,7 +41,15 @@ export async function runAgentLLM( subscriptionTier: SubscriptionTier ) { const phClient = new PostHog(process.env.POSTHOG_API_KEY!, { host: 'https://us.i.posthog.com' }); - const modelGoogle = withTracing(google('gemini-2.5-pro'), phClient, { + const modelGoogle = withTracing(google('gemini-3-flash-preview'), phClient, { + posthogTraceId: `agent_${agentId}_${previousMessages.length}`, + }); + + const openaiClient = createOpenAI({ + apiKey: process.env.OPENAI_API_KEY, + }); + + const modelOpenAI = withTracing(openaiClient('gpt-5-mini'), phClient, { posthogTraceId: `agent_${agentId}_${previousMessages.length}`, }); @@ -62,16 +70,22 @@ export async function runAgentLLM( const agent = new ToolLoopAgent({ model: modelGoogle, + providerOptions: { + openai: { + reasoningEffort: 'high', + reasoningSummary: 'concise', + }, + }, instructions: AGENT_SYSTEM_PROMPT, tools: { ...tools, ...dynamicTools, ...browserTools }, - stopWhen: stepCountIs(32), + stopWhen: stepCountIs(1024), onStepFinish: (step) => { streamReasoning(step); usageAccumulator.promptTokens += step.usage.inputTokens || 0; usageAccumulator.completionTokens += step.usage.outputTokens || 0; usageAccumulator.totalTokens += step.usage.totalTokens || 0; }, - maxRetries: 10, + maxRetries: 20, }); const result = await agent.generate({ messages }); diff --git a/backend/src/workflows/prompts.ts b/backend/src/workflows/prompts.ts index eb80274..c6d51cb 100644 --- a/backend/src/workflows/prompts.ts +++ b/backend/src/workflows/prompts.ts @@ -1,3 +1,19 @@ +const TOOL_OUTPUT_LIMITS = ` +## Tool Output Limits +Tool outputs are truncated to conserve context: + +- **readFile**: Returns up to 200 lines at a time with line numbers. Use \`startLine\` and \`limit\` parameters to paginate. + - If you see "...[showing lines X-Y of Z]", request the next range with \`startLine: Y+1\` + - For targeted reading, use runCommand with grep to find line numbers first: \`grep -n "pattern" file.ts\` + +- **runCommand**: Output is limited to 200 lines. + - If you see "...[showing X of Y lines]", the output was truncated + - To see specific parts: \`command | tail -100\` or \`command | head -100\` + - To capture full output: \`command > output.txt && wc -l output.txt\` + +When you see truncated output, decide if you need more context or can proceed with what you have. +`; + export const AGENT_SYSTEM_PROMPT = ` You are Codee, an asynchronous coding agent. You work on GitHub repositories, read code, make changes, and explain your steps succinctly. If the user requests git operations, prefer using tools (updateFile, listFiles, readFile, runCommand). @@ -5,7 +21,7 @@ Avoid destructive operations. Return concise reasoning and resulting changes. You are currently running in a FRESH sandbox. Before you were called, a fresh Node sandbox was created, and the repository was pulled from GitHub. Ensure while calling tools, you do ANY required setup. Do not assume things like node_module folders are included. - +${TOOL_OUTPUT_LIMITS} When using browser tools to test or interact with a web application: 1. Install dependencies first using runCommand (e.g., "npm install" or "bun install") 2. Start the dev server in background with logging to verify it starts correctly: @@ -64,4 +80,5 @@ You are the primary agent for the user in this case. You should spend a long tim use those tools. At the very end, you should spawn a number of agents to help you with the request. This is not the time to elicit feedback from the user. A user will only use a primary agent in order to have a lot of thinking done for other sub agents to be created. Under no circumstances should you finish a conversation without creating sub agents, unless there is truly no further work to be done relating to the request. +${TOOL_OUTPUT_LIMITS} `; diff --git a/backend/src/workflows/steps.ts b/backend/src/workflows/steps.ts index 55550f8..cdc2862 100644 --- a/backend/src/workflows/steps.ts +++ b/backend/src/workflows/steps.ts @@ -4,6 +4,7 @@ import { Sandbox } from '@vercel/sandbox'; import { Agent, AgentStatus } from '../db/entities/Agent'; import { Message } from '../db/entities/Message'; import { SubscriptionTier } from '../db/entities/Organization'; +import { Environment } from '../db/entities/Environment'; import { AppDataSource } from '../db/data-source'; import { emitDone, emitError, emitStatus } from '../stream/events'; import { getAgentById, saveMessage, saveAgentActivity, updateAgent } from './helpers/agents'; @@ -61,6 +62,36 @@ export async function loadPreviousMessages(agentId: number) { }); } +export async function writeEnvironmentFiles(agent: Agent, sandbox: Sandbox): Promise { + if (!agent.environmentId) { + return []; + } + + const environment = await AppDataSource.getRepository(Environment).findOne({ + where: { id: agent.environmentId }, + }); + + if (!environment || !environment.files?.length) { + return []; + } + + await emitStatus(agent.id, 'running', 'agent_env_files', 'writing environment files'); + + for (const file of environment.files) { + const dirPath = file.path.split('/').slice(0, -1).join('/'); + if (dirPath) { + await sandbox.runCommand({ + cmd: 'mkdir', + args: ['-p', dirPath], + }); + } + + await sandbox.writeFiles([{ path: file.path, content: Buffer.from(file.content, 'utf-8') }]); + } + + return environment.files.map((f) => f.path); +} + export async function createBranchIfNeeded(agent: Agent, sandbox: Sandbox, isOrchestratorAgent: boolean) { if (isOrchestratorAgent) { return null; @@ -116,17 +147,38 @@ export async function saveAgentResponse( return savedMessage; } -export async function commitChangesIfNeeded(sandbox: Sandbox, agentId: number, prompt: string) { +export async function commitChangesIfNeeded(sandbox: Sandbox, agentId: number, prompt: string, excludeFilePaths: string[] = []) { const statusResult = await sandbox.runCommand({ cmd: 'git', args: ['status', '--porcelain'], }); - const hasChanges = (await statusResult.stdout()).trim().length > 0; - if (hasChanges) { - await emitStatus(agentId, 'running', 'agent_commit', 'committing changes'); - const commitMessage = `Codee: ${prompt.slice(0, 50)}${prompt.length > 50 ? '...' : ''}`; - await commitAndPush(sandbox, commitMessage); + const statusOutput = (await statusResult.stdout()).trim(); + if (!statusOutput) { + return; + } + + if (excludeFilePaths.length > 0) { + for (const filePath of excludeFilePaths) { + await sandbox.runCommand({ + cmd: 'git', + args: ['checkout', '--', filePath], + }).catch(() => { + // File might be new (untracked), just skip + }); + } + + const statusAfterResult = await sandbox.runCommand({ + cmd: 'git', + args: ['status', '--porcelain'], + }); + if (!(await statusAfterResult.stdout()).trim()) { + return; + } } + + await emitStatus(agentId, 'running', 'agent_commit', 'committing changes'); + const commitMessage = `Codee: ${prompt.slice(0, 50)}${prompt.length > 50 ? '...' : ''}`; + await commitAndPush(sandbox, commitMessage); } export async function cleanupSandbox(sandbox: Sandbox, agentId?: number) { diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 37db15a..0a36b7a 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4,6 +4,7 @@ import Login from './pages/Login/Login'; import Home from './pages/Home/Home'; import Sidebar from './components/Sidebar/Sidebar'; import Integrations from './pages/Integrations/Integrations'; +import Environments from './pages/Environments/Environments'; import Workspace from './pages/Workspace/Workspace'; import Workers from './pages/Workers/Workers'; import Usage from './pages/Usage/Usage'; @@ -26,6 +27,7 @@ function App() { }> } /> } /> + } /> } /> } /> } /> diff --git a/frontend/src/components/Sidebar/Sidebar.tsx b/frontend/src/components/Sidebar/Sidebar.tsx index e872835..8bd9921 100644 --- a/frontend/src/components/Sidebar/Sidebar.tsx +++ b/frontend/src/components/Sidebar/Sidebar.tsx @@ -4,7 +4,7 @@ import SidebarButton from './SidebarButton'; import { useAuth } from '../../lib/useAuth'; import { NavLink, useNavigate } from 'react-router-dom'; import { trpc } from '../../lib/trpc'; -import { FiHome, FiGrid, FiUsers, FiLogOut, FiSettings, FiPieChart, FiBriefcase } from 'react-icons/fi'; +import { FiHome, FiGrid, FiUsers, FiLogOut, FiSettings, FiPieChart, FiBriefcase, FiLock } from 'react-icons/fi'; import codeeLogo from '../../assets/svgs/CodeeLogo.svg'; type SidebarProps = { @@ -30,6 +30,7 @@ export default function Sidebar({ children }: SidebarProps) {
} /> } /> + } /> } /> } /> } /> diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts index eabb8e7..937bdec 100644 --- a/frontend/src/lib/types.ts +++ b/frontend/src/lib/types.ts @@ -25,6 +25,8 @@ export type Message = Omit(null); + + return ( +
+

+

Environments

+ +

+ +
+ {environments?.length === 0 && ( +
No environments found. Create one to get started!
+ )} + {environments?.map((env) => ( +
setSelectedEnvironmentId(env.id)} + > +
{env.name}
+
+ + {env.github_repository_name} +
+ {env.description &&
{env.description}
} +
+ {env.file_paths.map((path) => ( + + {path} + + ))} +
+
+ ))} +
+ + setIsCreateModalOpen(false)} + /> + + setSelectedEnvironmentId(null)} + environmentId={selectedEnvironmentId} + /> +
+ ); +} diff --git a/frontend/src/pages/Environments/components/CreateEnvironmentModal.tsx b/frontend/src/pages/Environments/components/CreateEnvironmentModal.tsx new file mode 100644 index 0000000..6c4e9c6 --- /dev/null +++ b/frontend/src/pages/Environments/components/CreateEnvironmentModal.tsx @@ -0,0 +1,290 @@ +import { trpc } from '../../../lib/trpc'; +import type { Repository } from '../../../lib/types'; +import { useState, useEffect, useMemo, useRef } from 'react'; +import { GoRepo } from 'react-icons/go'; +import { FiPlus, FiX } from 'react-icons/fi'; +import styles from './styles.module.css'; + +interface EnvFile { + path: string; + content: string; +} + +interface CreateEnvironmentModalProps { + isOpen: boolean; + onClose: () => void; + environmentId?: number | null; +} + +export function CreateEnvironmentModal({ isOpen, onClose, environmentId }: CreateEnvironmentModalProps) { + const utils = trpc.useUtils(); + const createEnvironment = trpc.environments.create.useMutation({ + onSuccess: () => utils.environments.list.invalidate(), + }); + const updateEnvironment = trpc.environments.update.useMutation({ + onSuccess: () => utils.environments.list.invalidate(), + }); + const deleteEnvironment = trpc.environments.delete.useMutation({ + onSuccess: () => utils.environments.list.invalidate(), + }); + + const { data: environment } = trpc.environments.get.useQuery( + { id: environmentId! }, + { enabled: isOpen && !!environmentId } + ); + + const { data: repos } = trpc.integrations.repositories.useQuery(undefined, { + enabled: isOpen, + trpc: { context: { skipBatch: true } }, + }); + + const [name, setName] = useState(''); + const [description, setDescription] = useState(''); + const [selectedRepo, setSelectedRepo] = useState(''); + const [files, setFiles] = useState([{ path: '.env', content: '' }]); + const [error, setError] = useState(null); + const [isRepoDropdownOpen, setIsRepoDropdownOpen] = useState(false); + const [repoSearch, setRepoSearch] = useState(''); + const repoDropdownRef = useRef(null); + + useEffect(() => { + if (isOpen) { + setError(null); + if (environment) { + setName(environment.name); + setDescription(environment.description || ''); + setSelectedRepo(environment.github_repository_name); + setFiles( + environment.files.map((f) => ({ + path: f.path, + content: f.content, + })) + ); + } else { + setName(''); + setDescription(''); + setSelectedRepo(''); + setFiles([{ path: '.env', content: '' }]); + } + } + }, [isOpen, environment]); + + useEffect(() => { + function handleClickOutside(event: MouseEvent) { + if (repoDropdownRef.current && !repoDropdownRef.current.contains(event.target as Node)) { + setIsRepoDropdownOpen(false); + } + } + document.addEventListener('mousedown', handleClickOutside); + return () => document.removeEventListener('mousedown', handleClickOutside); + }, []); + + const filteredRepos = useMemo(() => { + const query = repoSearch.trim().toLowerCase(); + return (repos ?? []).filter((repo) => !query || repo.name.toLowerCase().includes(query)); + }, [repos, repoSearch]); + + if (!isOpen) return null; + + const isLoading = createEnvironment.isPending || updateEnvironment.isPending || deleteEnvironment.isPending; + + const handleAddFile = () => { + setFiles([...files, { path: '', content: '' }]); + }; + + const handleRemoveFile = (index: number) => { + setFiles(files.filter((_, i) => i !== index)); + }; + + const handleFileChange = (index: number, field: 'path' | 'content', value: string) => { + const newFiles = [...files]; + newFiles[index][field] = value; + setFiles(newFiles); + }; + + const handleSubmit = async () => { + setError(null); + + if (!name.trim()) { + setError('Name is required'); + return; + } + if (!selectedRepo) { + setError('Repository is required'); + return; + } + if (files.length === 0) { + setError('At least one .env file is required'); + return; + } + const invalidFiles = files.filter((f) => !f.path.trim()); + if (invalidFiles.length > 0) { + setError('All files must have a path'); + return; + } + + try { + const payload = { + name: name.trim(), + github_repository_name: selectedRepo, + description: description.trim() || undefined, + files: files.map((f) => ({ + path: f.path.trim(), + content: f.content, + })), + }; + + if (environment) { + await updateEnvironment.mutateAsync({ + id: environment.id, + ...payload, + }); + } else { + await createEnvironment.mutateAsync(payload); + } + onClose(); + } catch (err: unknown) { + const message = err && typeof err === 'object' && 'message' in err ? String((err as { message: string }).message) : 'Failed to save environment'; + setError(message); + } + }; + + const handleDelete = async () => { + if (!environment) return; + setError(null); + try { + await deleteEnvironment.mutateAsync({ id: environment.id }); + onClose(); + } catch (err: unknown) { + const message = err && typeof err === 'object' && 'message' in err ? String((err as { message: string }).message) : 'Failed to delete environment'; + setError(message); + } + }; + + return ( +
+
event.stopPropagation()}> +

{environment ? 'Edit Environment' : 'Create Environment'}

+ +
+ + setName(e.target.value)} + placeholder="Production, Staging, Development..." + /> +
+ +
+ +
+ + {isRepoDropdownOpen && ( +
+ setRepoSearch(e.target.value)} + onClick={(e) => e.stopPropagation()} + /> + {filteredRepos.map((repo) => ( +
{ + setSelectedRepo(repo.name); + setIsRepoDropdownOpen(false); + }} + > + + {repo.name} +
+ ))} +
+ )} +
+
+ +
+ +