diff --git a/apps/vscode-e2e/src/suite/tools/insert-content.test.ts b/apps/vscode-e2e/src/suite/tools/insert-content.test.ts deleted file mode 100644 index a3a3abb1866..00000000000 --- a/apps/vscode-e2e/src/suite/tools/insert-content.test.ts +++ /dev/null @@ -1,628 +0,0 @@ -import * as assert from "assert" -import * as fs from "fs/promises" -import * as path from "path" -import * as vscode from "vscode" - -import { RooCodeEventName, type ClineMessage } from "@roo-code/types" - -import { waitFor, sleep } from "../utils" -import { setDefaultSuiteTimeout } from "../test-utils" - -suite.skip("Roo Code insert_content Tool", function () { - setDefaultSuiteTimeout(this) - - let workspaceDir: string - - // Pre-created test files that will be used across tests - const testFiles = { - simpleText: { - name: `test-insert-simple-${Date.now()}.txt`, - content: "Line 1\nLine 2\nLine 3", - path: "", - }, - jsFile: { - name: `test-insert-js-${Date.now()}.js`, - content: `function hello() { - console.log("Hello World") -} - -function goodbye() { - console.log("Goodbye World") -}`, - path: "", - }, - emptyFile: { - name: `test-insert-empty-${Date.now()}.txt`, - content: "", - path: "", - }, - pythonFile: { - name: `test-insert-python-${Date.now()}.py`, - content: `def main(): - print("Start") - print("End")`, - path: "", - }, - } - - // Get the actual workspace directory that VSCode is using and create all test files - suiteSetup(async function () { - // Get the workspace folder from VSCode - const workspaceFolders = vscode.workspace.workspaceFolders - if (!workspaceFolders || workspaceFolders.length === 0) { - throw new Error("No workspace folder found") - } - workspaceDir = workspaceFolders[0]!.uri.fsPath - console.log("Using workspace directory:", workspaceDir) - - // Create all test files before any tests run - console.log("Creating test files in workspace...") - for (const [key, file] of Object.entries(testFiles)) { - file.path = path.join(workspaceDir, file.name) - await fs.writeFile(file.path, file.content) - console.log(`Created ${key} test file at:`, file.path) - } - - // Verify all files exist - for (const [key, file] of Object.entries(testFiles)) { - const exists = await fs - .access(file.path) - .then(() => true) - .catch(() => false) - if (!exists) { - throw new Error(`Failed to create ${key} test file at ${file.path}`) - } - } - }) - - // Clean up after all tests - suiteTeardown(async () => { - // Cancel any running tasks before cleanup - test("Should insert content at the beginning of a file (line 1)", async function () { - const api = globalThis.api - // Clean up before each test - setup(async () => { - // Cancel any previous task - try { - await globalThis.api.cancelCurrentTask() - } catch { - // Task might not be running - } - - // Small delay to ensure clean state - await sleep(100) - }) - - // Clean up after each test - teardown(async () => { - // Cancel the current task - try { - await globalThis.api.cancelCurrentTask() - } catch { - // Task might not be running - } - - // Small delay to ensure clean state - await sleep(100) - }) - const messages: ClineMessage[] = [] - const testFile = testFiles.simpleText - const insertContent = "New first line" - const expectedContent = `${insertContent} -${testFile.content}` - let taskStarted = false - let taskCompleted = false - let errorOccurred: string | null = null - let insertContentExecuted = false - - // Listen for messages - const messageHandler = ({ message }: { message: ClineMessage }) => { - messages.push(message) - - // Log important messages for debugging - if (message.type === "say" && message.say === "error") { - errorOccurred = message.text || "Unknown error" - console.error("Error:", message.text) - } - if (message.type === "ask" && message.ask === "tool") { - console.log("Tool request:", message.text?.substring(0, 200)) - } - if (message.type === "say" && (message.say === "completion_result" || message.say === "text")) { - console.log("AI response:", message.text?.substring(0, 200)) - } - - // Check for tool execution - if (message.type === "say" && message.say === "api_req_started" && message.text) { - console.log("API request started:", message.text.substring(0, 200)) - try { - const requestData = JSON.parse(message.text) - if (requestData.request && requestData.request.includes("insert_content")) { - insertContentExecuted = true - console.log("insert_content tool executed!") - } - } catch (e) { - console.log("Failed to parse api_req_started message:", e) - } - } - } - api.on(RooCodeEventName.Message, messageHandler) - - // Listen for task events - const taskStartedHandler = (id: string) => { - if (id === taskId) { - taskStarted = true - console.log("Task started:", id) - } - } - api.on(RooCodeEventName.TaskStarted, taskStartedHandler) - - const taskCompletedHandler = (id: string) => { - if (id === taskId) { - taskCompleted = true - console.log("Task completed:", id) - } - } - api.on(RooCodeEventName.TaskCompleted, taskCompletedHandler) - - let taskId: string - try { - // Start the task - taskId = await api.startNewTask({ - configuration: { - mode: "code", - autoApprovalEnabled: true, - alwaysAllowWrite: true, - alwaysAllowReadOnly: true, - alwaysAllowReadOnlyOutsideWorkspace: true, - }, - text: `Use insert_content to add "${insertContent}" at line 1 (beginning) of the file ${testFile.name}. The file already exists with this content: -${testFile.content} - -Assume the file exists and you can modify it directly.`, - }) - - console.log("Task ID:", taskId) - console.log("Test filename:", testFile.name) - - // Wait for task to start - await waitFor(() => taskStarted, { timeout: 45_000 }) - - // Check for early errors - if (errorOccurred) { - console.error("Early error detected:", errorOccurred) - } - - // Wait for task completion - await waitFor(() => taskCompleted, { timeout: 45_000 }) - - // Give extra time for file system operations - await sleep(2000) - - // Check if the file was modified correctly - const actualContent = await fs.readFile(testFile.path, "utf-8") - console.log("File content after insertion:", actualContent) - - // Verify tool was executed - assert.strictEqual(insertContentExecuted, true, "insert_content tool should have been executed") - - // Verify file content - assert.strictEqual( - actualContent.trim(), - expectedContent.trim(), - "Content should be inserted at the beginning of the file", - ) - - // Verify no errors occurred - assert.strictEqual( - errorOccurred, - null, - `Task should complete without errors, but got: ${errorOccurred}`, - ) - - console.log("Test passed! insert_content tool executed and content inserted at beginning successfully") - } finally { - api.off(RooCodeEventName.Message, messageHandler) - api.off(RooCodeEventName.TaskStarted, taskStartedHandler) - api.off(RooCodeEventName.TaskCompleted, taskCompletedHandler) - } - }) - try { - await globalThis.api.cancelCurrentTask() - } catch { - // Task might not be running - } - - // Clean up all test files - console.log("Cleaning up test files...") - for (const [key, file] of Object.entries(testFiles)) { - try { - await fs.unlink(file.path) - console.log(`Cleaned up ${key} test file`) - } catch (error) { - console.log(`Failed to clean up ${key} test file:`, error) - } - } - }) - - test("Should insert content at the end of a file (line 0)", async function () { - const api = globalThis.api - const messages: ClineMessage[] = [] - const testFile = testFiles.simpleText - const insertContent = "New last line" - const expectedContent = `${testFile.content} -${insertContent}` - let taskStarted = false - let taskCompleted = false - let errorOccurred: string | null = null - let insertContentExecuted = false - - // Listen for messages - const messageHandler = ({ message }: { message: ClineMessage }) => { - messages.push(message) - - // Log important messages for debugging - if (message.type === "say" && message.say === "error") { - errorOccurred = message.text || "Unknown error" - console.error("Error:", message.text) - } - if (message.type === "ask" && message.ask === "tool") { - console.log("Tool request:", message.text?.substring(0, 200)) - } - if (message.type === "say" && (message.say === "completion_result" || message.say === "text")) { - console.log("AI response:", message.text?.substring(0, 200)) - } - - // Check for tool execution - if (message.type === "say" && message.say === "api_req_started" && message.text) { - console.log("API request started:", message.text.substring(0, 200)) - try { - const requestData = JSON.parse(message.text) - if (requestData.request && requestData.request.includes("insert_content")) { - insertContentExecuted = true - console.log("insert_content tool executed!") - } - } catch (e) { - console.log("Failed to parse api_req_started message:", e) - } - } - } - api.on(RooCodeEventName.Message, messageHandler) - - // Listen for task events - const taskStartedHandler = (id: string) => { - if (id === taskId) { - taskStarted = true - console.log("Task started:", id) - } - } - api.on(RooCodeEventName.TaskStarted, taskStartedHandler) - - const taskCompletedHandler = (id: string) => { - if (id === taskId) { - taskCompleted = true - console.log("Task completed:", id) - } - } - api.on(RooCodeEventName.TaskCompleted, taskCompletedHandler) - - let taskId: string - try { - // Start the task - taskId = await api.startNewTask({ - configuration: { - mode: "code", - autoApprovalEnabled: true, - alwaysAllowWrite: true, - alwaysAllowReadOnly: true, - alwaysAllowReadOnlyOutsideWorkspace: true, - }, - text: `Use insert_content to add "${insertContent}" at line 0 (end of file) of the file ${testFile.name}. The file already exists with this content: -${testFile.content} - -Assume the file exists and you can modify it directly.`, - }) - - console.log("Task ID:", taskId) - console.log("Test filename:", testFile.name) - - // Wait for task to start - await waitFor(() => taskStarted, { timeout: 45_000 }) - - // Check for early errors - if (errorOccurred) { - console.error("Early error detected:", errorOccurred) - } - - // Wait for task completion - await waitFor(() => taskCompleted, { timeout: 45_000 }) - - // Give extra time for file system operations - await sleep(2000) - - // Check if the file was modified correctly - const actualContent = await fs.readFile(testFile.path, "utf-8") - console.log("File content after insertion:", actualContent) - - // Verify tool was executed - test("Should insert multiline content into a JavaScript file", async function () { - const api = globalThis.api - const messages: ClineMessage[] = [] - const testFile = testFiles.jsFile - const insertContent = `// New import statements -import { utils } from './utils' -import { helpers } from './helpers'` - const expectedContent = `${insertContent} -${testFile.content}` - let taskStarted = false - let taskCompleted = false - let errorOccurred: string | null = null - let insertContentExecuted = false - - // Listen for messages - const messageHandler = ({ message }: { message: ClineMessage }) => { - messages.push(message) - - // Log important messages for debugging - if (message.type === "say" && message.say === "error") { - errorOccurred = message.text || "Unknown error" - console.error("Error:", message.text) - } - if (message.type === "ask" && message.ask === "tool") { - console.log("Tool request:", message.text?.substring(0, 200)) - } - if (message.type === "say" && (message.say === "completion_result" || message.say === "text")) { - console.log("AI response:", message.text?.substring(0, 200)) - } - - // Check for tool execution - if (message.type === "say" && message.say === "api_req_started" && message.text) { - console.log("API request started:", message.text.substring(0, 200)) - try { - const requestData = JSON.parse(message.text) - if (requestData.request && requestData.request.includes("insert_content")) { - insertContentExecuted = true - console.log("insert_content tool executed!") - } - } catch (e) { - console.log("Failed to parse api_req_started message:", e) - } - } - } - api.on(RooCodeEventName.Message, messageHandler) - - // Listen for task events - const taskStartedHandler = (id: string) => { - if (id === taskId) { - taskStarted = true - console.log("Task started:", id) - } - } - api.on(RooCodeEventName.TaskStarted, taskStartedHandler) - - const taskCompletedHandler = (id: string) => { - if (id === taskId) { - taskCompleted = true - console.log("Task completed:", id) - } - } - api.on(RooCodeEventName.TaskCompleted, taskCompletedHandler) - - let taskId: string - try { - // Start the task - taskId = await api.startNewTask({ - configuration: { - mode: "code", - autoApprovalEnabled: true, - alwaysAllowWrite: true, - alwaysAllowReadOnly: true, - alwaysAllowReadOnlyOutsideWorkspace: true, - }, - text: `Use insert_content to add import statements at the beginning (line 1) of the JavaScript file ${testFile.name}. Add these lines: -${insertContent} - -The file already exists with this content: -${testFile.content} - -Assume the file exists and you can modify it directly.`, - }) - - console.log("Task ID:", taskId) - console.log("Test filename:", testFile.name) - - // Wait for task to start - await waitFor(() => taskStarted, { timeout: 45_000 }) - - // Check for early errors - if (errorOccurred) { - console.error("Early error detected:", errorOccurred) - } - - // Wait for task completion - await waitFor(() => taskCompleted, { timeout: 45_000 }) - - // Give extra time for file system operations - await sleep(2000) - - test("Should insert content into an empty file", async function () { - const api = globalThis.api - const messages: ClineMessage[] = [] - const testFile = testFiles.emptyFile - const insertContent = `# My New File -This is the first line of content -And this is the second line` - const expectedContent = insertContent - let taskStarted = false - let taskCompleted = false - let errorOccurred: string | null = null - let insertContentExecuted = false - - // Listen for messages - const messageHandler = ({ message }: { message: ClineMessage }) => { - messages.push(message) - - // Log important messages for debugging - if (message.type === "say" && message.say === "error") { - errorOccurred = message.text || "Unknown error" - console.error("Error:", message.text) - } - if (message.type === "ask" && message.ask === "tool") { - console.log("Tool request:", message.text?.substring(0, 200)) - } - if ( - message.type === "say" && - (message.say === "completion_result" || message.say === "text") - ) { - console.log("AI response:", message.text?.substring(0, 200)) - } - - // Check for tool execution - if (message.type === "say" && message.say === "api_req_started" && message.text) { - console.log("API request started:", message.text.substring(0, 200)) - try { - const requestData = JSON.parse(message.text) - if (requestData.request && requestData.request.includes("insert_content")) { - insertContentExecuted = true - console.log("insert_content tool executed!") - } - } catch (e) { - console.log("Failed to parse api_req_started message:", e) - } - } - } - api.on(RooCodeEventName.Message, messageHandler) - - // Listen for task events - const taskStartedHandler = (id: string) => { - if (id === taskId) { - taskStarted = true - console.log("Task started:", id) - } - } - api.on(RooCodeEventName.TaskStarted, taskStartedHandler) - - const taskCompletedHandler = (id: string) => { - if (id === taskId) { - taskCompleted = true - console.log("Task completed:", id) - } - } - api.on(RooCodeEventName.TaskCompleted, taskCompletedHandler) - - let taskId: string - try { - // Start the task - taskId = await api.startNewTask({ - configuration: { - mode: "code", - autoApprovalEnabled: true, - alwaysAllowWrite: true, - alwaysAllowReadOnly: true, - alwaysAllowReadOnlyOutsideWorkspace: true, - }, - text: `Use insert_content to add content to the empty file ${testFile.name}. Add this content at line 0 (end of file): -${insertContent} - -The file is currently empty. Assume the file exists and you can modify it directly.`, - }) - - console.log("Task ID:", taskId) - console.log("Test filename:", testFile.name) - - // Wait for task to start - await waitFor(() => taskStarted, { timeout: 45_000 }) - - // Check for early errors - if (errorOccurred) { - console.error("Early error detected:", errorOccurred) - } - - // Wait for task completion - await waitFor(() => taskCompleted, { timeout: 45_000 }) - - // Give extra time for file system operations - await sleep(2000) - - // Check if the file was modified correctly - const actualContent = await fs.readFile(testFile.path, "utf-8") - console.log("File content after insertion:", actualContent) - - // Verify tool was executed - assert.strictEqual( - insertContentExecuted, - true, - "insert_content tool should have been executed", - ) - - // Verify file content - assert.strictEqual( - actualContent.trim(), - expectedContent.trim(), - "Content should be inserted into the empty file", - ) - - // Verify no errors occurred - assert.strictEqual( - errorOccurred, - null, - `Task should complete without errors, but got: ${errorOccurred}`, - ) - - console.log( - "Test passed! insert_content tool executed and content inserted into empty file successfully", - ) - } finally { - api.off(RooCodeEventName.Message, messageHandler) - api.off(RooCodeEventName.TaskStarted, taskStartedHandler) - api.off(RooCodeEventName.TaskCompleted, taskCompletedHandler) - } - }) - // Check if the file was modified correctly - const actualContent = await fs.readFile(testFile.path, "utf-8") - console.log("File content after insertion:", actualContent) - - // Verify tool was executed - assert.strictEqual(insertContentExecuted, true, "insert_content tool should have been executed") - - // Verify file content - assert.strictEqual( - actualContent.trim(), - expectedContent.trim(), - "Multiline content should be inserted at the beginning of the JavaScript file", - ) - - // Verify no errors occurred - assert.strictEqual( - errorOccurred, - null, - `Task should complete without errors, but got: ${errorOccurred}`, - ) - - console.log("Test passed! insert_content tool executed and multiline content inserted successfully") - } finally { - api.off(RooCodeEventName.Message, messageHandler) - api.off(RooCodeEventName.TaskStarted, taskStartedHandler) - api.off(RooCodeEventName.TaskCompleted, taskCompletedHandler) - } - }) - assert.strictEqual(insertContentExecuted, true, "insert_content tool should have been executed") - - // Verify file content - assert.strictEqual( - actualContent.trim(), - expectedContent.trim(), - "Content should be inserted at the end of the file", - ) - - // Verify no errors occurred - assert.strictEqual(errorOccurred, null, `Task should complete without errors, but got: ${errorOccurred}`) - - console.log("Test passed! insert_content tool executed and content inserted at end successfully") - } finally { - api.off(RooCodeEventName.Message, messageHandler) - api.off(RooCodeEventName.TaskStarted, taskStartedHandler) - api.off(RooCodeEventName.TaskCompleted, taskCompletedHandler) - } - }) - // Tests will be added here one by one -}) diff --git a/apps/web-evals/package.json b/apps/web-evals/package.json index d2e93599469..b2ac0d43460 100644 --- a/apps/web-evals/package.json +++ b/apps/web-evals/package.json @@ -35,7 +35,7 @@ "cmdk": "^1.1.0", "fuzzysort": "^3.1.0", "lucide-react": "^0.518.0", - "next": "^15.2.5", + "next": "~15.2.6", "next-themes": "^0.4.6", "p-map": "^7.0.3", "react": "^18.3.1", diff --git a/apps/web-roo-code/package.json b/apps/web-roo-code/package.json index 1cf8d4dd178..cd5af759bec 100644 --- a/apps/web-roo-code/package.json +++ b/apps/web-roo-code/package.json @@ -25,7 +25,7 @@ "embla-carousel-react": "^8.6.0", "framer-motion": "12.15.0", "lucide-react": "^0.518.0", - "next": "^15.2.5", + "next": "~15.2.6", "next-themes": "^0.4.6", "posthog-js": "^1.248.1", "react": "^18.3.1", diff --git a/packages/types/src/message.ts b/packages/types/src/message.ts index 0f25fe53305..a857aacd3a4 100644 --- a/packages/types/src/message.ts +++ b/packages/types/src/message.ts @@ -175,6 +175,7 @@ export const clineSays = [ "diff_error", "condense_context", "condense_context_error", + "sliding_window_truncation", "codebase_search_result", "user_edit_todos", ] as const @@ -203,10 +204,25 @@ export const contextCondenseSchema = z.object({ prevContextTokens: z.number(), newContextTokens: z.number(), summary: z.string(), + condenseId: z.string().optional(), }) export type ContextCondense = z.infer +/** + * ContextTruncation + * + * Used to track sliding window truncation events for the UI. + */ + +export const contextTruncationSchema = z.object({ + truncationId: z.string(), + messagesRemoved: z.number(), + prevContextTokens: z.number(), +}) + +export type ContextTruncation = z.infer + /** * ClineMessage */ @@ -225,6 +241,7 @@ export const clineMessageSchema = z.object({ checkpoint: z.record(z.string(), z.unknown()).optional(), progressStatus: toolProgressStatusSchema.optional(), contextCondense: contextCondenseSchema.optional(), + contextTruncation: contextTruncationSchema.optional(), isProtected: z.boolean().optional(), apiProtocol: z.union([z.literal("openai"), z.literal("anthropic")]).optional(), isAnswered: z.boolean().optional(), diff --git a/packages/types/src/tool.ts b/packages/types/src/tool.ts index e6649e08206..ebb77b5d18a 100644 --- a/packages/types/src/tool.ts +++ b/packages/types/src/tool.ts @@ -19,7 +19,6 @@ export const toolNames = [ "read_file", "write_to_file", "apply_diff", - "insert_content", "search_and_replace", "apply_patch", "search_files", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fdbbea4231c..56d2049345c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,7 +20,7 @@ importers: devDependencies: '@changesets/cli': specifier: ^2.27.10 - version: 2.29.7(@types/node@24.10.1) + version: 2.29.8(@types/node@24.10.1) '@dotenvx/dotenvx': specifier: ^1.34.0 version: 1.51.1 @@ -38,7 +38,7 @@ importers: version: 3.3.2 esbuild: specifier: '>=0.25.0' - version: 0.27.0 + version: 0.27.1 eslint: specifier: ^9.27.0 version: 9.39.1(jiti@2.6.1) @@ -50,7 +50,7 @@ importers: version: 9.1.7 knip: specifier: ^5.44.4 - version: 5.70.1(@types/node@24.10.1)(typescript@5.8.3) + version: 5.71.0(@types/node@24.10.1)(typescript@5.8.3) lint-staged: specifier: ^16.0.0 version: 16.2.7 @@ -59,22 +59,22 @@ importers: version: 3.0.1 only-allow: specifier: ^1.2.1 - version: 1.2.1 + version: 1.2.2 ovsx: specifier: 0.10.4 version: 0.10.4 prettier: specifier: ^3.4.2 - version: 3.6.2 + version: 3.7.4 rimraf: specifier: ^6.0.1 version: 6.1.2 tsx: specifier: ^4.19.3 - version: 4.20.6 + version: 4.21.0 turbo: specifier: ^2.5.6 - version: 2.6.1 + version: 2.6.2 typescript: specifier: ^5.4.5 version: 5.8.3 @@ -128,7 +128,7 @@ importers: dependencies: '@hookform/resolvers': specifier: ^5.1.1 - version: 5.2.2(react-hook-form@7.66.1(react@18.3.1)) + version: 5.2.2(react-hook-form@7.68.0(react@18.3.1)) '@radix-ui/react-alert-dialog': specifier: ^1.1.7 version: 1.1.15(@types/react-dom@18.3.7(@types/react@18.3.27))(@types/react@18.3.27)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -176,7 +176,7 @@ importers: version: link:../../packages/types '@tanstack/react-query': specifier: ^5.69.0 - version: 5.90.10(react@18.3.1) + version: 5.90.11(react@18.3.1) archiver: specifier: ^7.0.1 version: 7.0.1 @@ -196,8 +196,8 @@ importers: specifier: ^0.518.0 version: 0.518.0(react@18.3.1) next: - specifier: ^15.2.5 - version: 15.5.6(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ~15.2.6 + version: 15.2.6(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-themes: specifier: ^0.4.6 version: 0.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -212,7 +212,7 @@ importers: version: 18.3.1(react@18.3.1) react-hook-form: specifier: ^7.57.0 - version: 7.66.1(react@18.3.1) + version: 7.68.0(react@18.3.1) react-use: specifier: ^17.6.0 version: 17.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -261,7 +261,7 @@ importers: version: 4.1.17 vitest: specifier: ^3.2.3 - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) apps/web-roo-code: dependencies: @@ -279,7 +279,7 @@ importers: version: link:../../packages/types '@tanstack/react-query': specifier: ^5.79.0 - version: 5.90.10(react@18.3.1) + version: 5.90.11(react@18.3.1) '@vercel/og': specifier: ^0.6.2 version: 0.6.8 @@ -305,14 +305,14 @@ importers: specifier: ^0.518.0 version: 0.518.0(react@18.3.1) next: - specifier: ^15.2.5 - version: 15.5.6(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ~15.2.6 + version: 15.2.6(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-themes: specifier: ^0.4.6 version: 0.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) posthog-js: specifier: ^1.248.1 - version: 1.297.2 + version: 1.301.0 react: specifier: ^18.3.1 version: 18.3.1 @@ -342,7 +342,7 @@ importers: version: 3.4.0 tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1)) + version: 1.0.7(tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.2)) tldts: specifier: ^6.1.86 version: 6.1.86 @@ -358,7 +358,7 @@ importers: version: link:../../packages/config-typescript '@tailwindcss/typography': specifier: ^0.5.16 - version: 0.5.19(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1)) + version: 0.5.19(tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.2)) '@types/node': specifier: 20.x version: 20.19.25 @@ -373,13 +373,13 @@ importers: version: 10.4.22(postcss@8.5.6) next-sitemap: specifier: ^4.2.3 - version: 4.2.3(next@15.5.6(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + version: 4.2.3(next@15.2.6(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) postcss: specifier: ^8.5.4 version: 8.5.6 tailwindcss: specifier: ^3.4.17 - version: 3.4.18(tsx@4.20.6)(yaml@2.8.1) + version: 3.4.18(tsx@4.21.0)(yaml@2.8.2) packages/build: dependencies: @@ -398,7 +398,7 @@ importers: version: 20.19.25 vitest: specifier: ^3.2.3 - version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) packages/cloud: dependencies: @@ -438,7 +438,7 @@ importers: version: 16.5.0 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) packages/config-eslint: devDependencies: @@ -447,7 +447,7 @@ importers: version: 9.39.1 '@next/eslint-plugin-next': specifier: ^15.2.1 - version: 15.5.6 + version: 15.5.7 eslint: specifier: ^9.27.0 version: 9.39.1(jiti@2.6.1) @@ -465,13 +465,13 @@ importers: version: 5.2.0(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-turbo: specifier: ^2.4.4 - version: 2.6.1(eslint@9.39.1(jiti@2.6.1))(turbo@2.6.1) + version: 2.6.2(eslint@9.39.1(jiti@2.6.1))(turbo@2.6.2) globals: specifier: ^16.0.0 version: 16.5.0 typescript-eslint: specifier: ^8.26.0 - version: 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) + version: 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) packages/config-typescript: {} @@ -491,7 +491,7 @@ importers: version: 0.44.7(@opentelemetry/api@1.9.0)(postgres@3.4.7) execa: specifier: ^9.6.0 - version: 9.6.0 + version: 9.6.1 node-ipc: specifier: ^12.0.0 version: 12.0.0 @@ -537,10 +537,10 @@ importers: version: 0.31.7 tsx: specifier: ^4.19.3 - version: 4.20.6 + version: 4.21.0 vitest: specifier: ^3.2.3 - version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) packages/ipc: dependencies: @@ -565,7 +565,7 @@ importers: version: 9.2.3 vitest: specifier: ^3.2.3 - version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) packages/telemetry: dependencies: @@ -586,7 +586,7 @@ importers: version: 4.17.21 posthog-node: specifier: ^5.0.0 - version: 5.13.2 + version: 5.17.0 prom-client: specifier: ^15.1.3 version: 15.1.3 @@ -608,7 +608,7 @@ importers: version: 1.4.9 '@types/lodash': specifier: ^4.17.20 - version: 4.17.20 + version: 4.17.21 '@types/node': specifier: 20.x version: 20.19.25 @@ -620,7 +620,7 @@ importers: version: 1.106.1 vitest: specifier: ^3.2.3 - version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) packages/types: dependencies: @@ -642,10 +642,10 @@ importers: version: 16.5.0 tsup: specifier: ^8.3.5 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.6)(typescript@5.8.3)(yaml@2.8.1) + version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2) vitest: specifier: ^3.2.3 - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) src: dependencies: @@ -660,13 +660,13 @@ importers: version: 0.7.0 '@aws-sdk/client-bedrock-runtime': specifier: ^3.922.0 - version: 3.936.0 + version: 3.943.0 '@aws-sdk/credential-providers': specifier: ^3.922.0 - version: 3.936.0 + version: 3.943.0 '@google/genai': specifier: ^1.29.1 - version: 1.30.0(@modelcontextprotocol/sdk@1.22.0) + version: 1.31.0(@modelcontextprotocol/sdk@1.24.2(zod@3.25.76)) '@lmstudio/sdk': specifier: ^1.1.1 version: 1.5.0 @@ -675,10 +675,10 @@ importers: version: 1.10.0 '@modelcontextprotocol/sdk': specifier: ^1.13.3 - version: 1.22.0 + version: 1.24.2(zod@3.25.76) '@qdrant/js-client-rest': specifier: ^1.14.0 - version: 1.16.0(typescript@5.8.3) + version: 1.16.2(typescript@5.8.3) '@roo-code/cloud': specifier: workspace:^ version: link:../packages/cloud @@ -759,7 +759,7 @@ importers: version: 4.0.3 i18next: specifier: ^25.0.0 - version: 25.6.3(typescript@5.8.3) + version: 25.7.1(typescript@5.8.3) iconv-lite: specifier: ^0.7.0 version: 0.7.0 @@ -780,7 +780,7 @@ importers: version: 4.0.8 lru-cache: specifier: ^11.1.0 - version: 11.2.2 + version: 11.2.4 mammoth: specifier: ^1.9.1 version: 1.11.0 @@ -819,7 +819,7 @@ importers: version: 1.1.4 pkce-challenge: specifier: ^5.0.0 - version: 5.0.0 + version: 5.0.1 pretty-bytes: specifier: ^7.0.0 version: 7.1.0 @@ -900,7 +900,7 @@ importers: version: 9.3.4 yaml: specifier: ^2.8.0 - version: 2.8.1 + version: 2.8.2 zod: specifier: ^3.25.61 version: 3.25.76 @@ -979,10 +979,10 @@ importers: version: 3.3.2 esbuild: specifier: '>=0.25.0' - version: 0.27.0 + version: 0.27.1 execa: specifier: ^9.5.2 - version: 9.6.0 + version: 9.6.1 glob: specifier: '>=11.1.0' version: 13.0.0 @@ -1003,16 +1003,16 @@ importers: version: 6.1.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.6)(typescript@5.8.3)(yaml@2.8.1) + version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2) tsx: specifier: ^4.19.3 - version: 4.20.6 + version: 4.21.0 typescript: specifier: 5.8.3 version: 5.8.3 vitest: specifier: ^3.2.3 - version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) zod-to-ts: specifier: ^1.2.0 version: 1.2.0(typescript@5.8.3)(zod@3.25.76) @@ -1066,10 +1066,10 @@ importers: version: link:../packages/types '@tailwindcss/vite': specifier: ^4.0.0 - version: 4.1.17(vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1)) + version: 4.1.17(vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/react-query': specifier: ^5.68.0 - version: 5.90.10(react@18.3.1) + version: 5.90.11(react@18.3.1) '@types/qrcode': specifier: ^1.5.5 version: 1.5.6 @@ -1111,7 +1111,7 @@ importers: version: 2.3.6 i18next: specifier: ^25.0.0 - version: 25.6.3(typescript@5.8.3) + version: 25.7.1(typescript@5.8.3) i18next-http-backend: specifier: ^3.0.2 version: 3.0.2 @@ -1126,16 +1126,16 @@ importers: version: 4.17.21 lru-cache: specifier: ^11.1.0 - version: 11.2.2 + version: 11.2.4 lucide-react: specifier: ^0.518.0 version: 0.518.0(react@18.3.1) mermaid: specifier: ^11.4.1 - version: 11.12.1 + version: 11.12.2 posthog-js: specifier: ^1.227.2 - version: 1.297.2 + version: 1.301.0 pretty-bytes: specifier: ^7.0.0 version: 7.1.0 @@ -1150,7 +1150,7 @@ importers: version: 18.3.1(react@18.3.1) react-i18next: specifier: ^15.4.1 - version: 15.7.4(i18next@25.6.3(typescript@5.8.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) + version: 15.7.4(i18next@25.7.1(typescript@5.8.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) react-markdown: specifier: ^9.0.3 version: 9.1.0(@types/react@18.3.27)(react@18.3.1) @@ -1165,7 +1165,7 @@ importers: version: 17.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-virtuoso: specifier: ^4.14.1 - version: 4.14.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 4.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rehype-highlight: specifier: ^7.0.0 version: 7.0.2 @@ -1192,7 +1192,7 @@ importers: version: 1.8.3 shiki: specifier: ^3.2.1 - version: 3.15.0 + version: 3.19.0 source-map: specifier: ^0.7.4 version: 0.7.6 @@ -1274,7 +1274,7 @@ importers: version: 1.57.5 '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1)) + version: 4.7.0(vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/ui': specifier: ^3.2.3 version: 3.2.4(vitest@3.2.4) @@ -1289,10 +1289,10 @@ importers: version: 5.8.3 vite: specifier: 6.3.6 - version: 6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + version: 6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) vitest: specifier: ^3.2.3 - version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) packages: @@ -1306,9 +1306,6 @@ packages: '@antfu/install-pkg@1.1.0': resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} - '@antfu/utils@9.3.0': - resolution: {integrity: sha512-9hFT4RauhcUzqOE4f1+frMKLZrgNog5b06I7VmZQV1BkvwvqrbC8EBZf3L1eEL2AKb6rNKjER0sEvJiSP1FXEA==} - '@anthropic-ai/bedrock-sdk@0.10.4': resolution: {integrity: sha512-szduEHbMli6XL934xrraYg5cFuKL/1oMyj/iZuEVjtddQ7eD5cXObzWobsv5mTLWijQmSzMfFD+JAUHDPHlQ/Q==} @@ -1350,60 +1347,60 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-bedrock-runtime@3.936.0': - resolution: {integrity: sha512-/Zy+0h7T4ftoIB7rr0dm1PlYkzQ46Q+L6ZPo63J5RpZ+CCavcARxjtqRUOqdBuT/LBNyWnCqaQ9wVpg5mJyUzw==} + '@aws-sdk/client-bedrock-runtime@3.943.0': + resolution: {integrity: sha512-mEiv1g5BeZFIQjBrzM5nT//KYLOBwUkXtHzsufkV99TIEKW5qzgOgx9Q9O8IbFQk3c7C6HYkV/kNOUI3KGyH6g==} engines: {node: '>=18.0.0'} - '@aws-sdk/client-cognito-identity@3.936.0': - resolution: {integrity: sha512-AkJZ426y0G8Lsyi9p7mWudacMKeo8XLZOfxUmeThMkDa3GxGQ1y6BTrOj6ZcvqQ1Hz7Abb3QWPC+EMqhu1Lncw==} + '@aws-sdk/client-cognito-identity@3.943.0': + resolution: {integrity: sha512-XkuokRF2IQ+VLBn0AwrwfFOkZ2c1IXACwQdn3CDnpBZpT1s2hgH3MX0DoH9+41w4ar2QCSI09uAJiv9PX4DLoQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/client-sso@3.936.0': - resolution: {integrity: sha512-0G73S2cDqYwJVvqL08eakj79MZG2QRaB56Ul8/Ps9oQxllr7DMI1IQ/N3j3xjxgpq/U36pkoFZ8aK1n7Sbr3IQ==} + '@aws-sdk/client-sso@3.943.0': + resolution: {integrity: sha512-kOTO2B8Ks2qX73CyKY8PAajtf5n39aMe2spoiOF5EkgSzGV7hZ/HONRDyADlyxwfsX39Q2F2SpPUaXzon32IGw==} engines: {node: '>=18.0.0'} - '@aws-sdk/core@3.936.0': - resolution: {integrity: sha512-eGJ2ySUMvgtOziHhDRDLCrj473RJoL4J1vPjVM3NrKC/fF3/LoHjkut8AAnKmrW6a2uTzNKubigw8dEnpmpERw==} + '@aws-sdk/core@3.943.0': + resolution: {integrity: sha512-8CBy2hI9ABF7RBVQuY1bgf/ue+WPmM/hl0adrXFlhnhkaQP0tFY5zhiy1Y+n7V+5f3/ORoHBmCCQmcHDDYJqJQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-cognito-identity@3.936.0': - resolution: {integrity: sha512-+aSC59yiD4M5RcYp9Gx3iwX/n4hO3ZWA2Mxmkzmt9gYFBbJ9umx2LpBdrV64y57AtOvfGeo0h7PAXniIufagxw==} + '@aws-sdk/credential-provider-cognito-identity@3.943.0': + resolution: {integrity: sha512-jZJ0uHjNlhfjx2ZX7YVYnh1wfSkLAvQmecGCSl9C6LJRNXy4uWFPbGjPqcA0tWp0WWIsUYhqjasgvCOMZIY8nw==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-env@3.936.0': - resolution: {integrity: sha512-dKajFuaugEA5i9gCKzOaVy9uTeZcApE+7Z5wdcZ6j40523fY1a56khDAUYkCfwqa7sHci4ccmxBkAo+fW1RChA==} + '@aws-sdk/credential-provider-env@3.943.0': + resolution: {integrity: sha512-WnS5w9fK9CTuoZRVSIHLOMcI63oODg9qd1vXMYb7QGLGlfwUm4aG3hdu7i9XvYrpkQfE3dzwWLtXF4ZBuL1Tew==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-http@3.936.0': - resolution: {integrity: sha512-5FguODLXG1tWx/x8fBxH+GVrk7Hey2LbXV5h9SFzYCx/2h50URBm0+9hndg0Rd23+xzYe14F6SI9HA9c1sPnjg==} + '@aws-sdk/credential-provider-http@3.943.0': + resolution: {integrity: sha512-SA8bUcYDEACdhnhLpZNnWusBpdmj4Vl67Vxp3Zke7SvoWSYbuxa+tiDiC+c92Z4Yq6xNOuLPW912ZPb9/NsSkA==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-ini@3.936.0': - resolution: {integrity: sha512-TbUv56ERQQujoHcLMcfL0Q6bVZfYF83gu/TjHkVkdSlHPOIKaG/mhE2XZSQzXv1cud6LlgeBbfzVAxJ+HPpffg==} + '@aws-sdk/credential-provider-ini@3.943.0': + resolution: {integrity: sha512-BcLDb8l4oVW+NkuqXMlO7TnM6lBOWW318ylf4FRED/ply5eaGxkQYqdGvHSqGSN5Rb3vr5Ek0xpzSjeYD7C8Kw==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-login@3.936.0': - resolution: {integrity: sha512-8DVrdRqPyUU66gfV7VZNToh56ZuO5D6agWrkLQE/xbLJOm2RbeRgh6buz7CqV8ipRd6m+zCl9mM4F3osQLZn8Q==} + '@aws-sdk/credential-provider-login@3.943.0': + resolution: {integrity: sha512-9iCOVkiRW+evxiJE94RqosCwRrzptAVPhRhGWv4osfYDhjNAvUMyrnZl3T1bjqCoKNcETRKEZIU3dqYHnUkcwQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-node@3.936.0': - resolution: {integrity: sha512-rk/2PCtxX9xDsQW8p5Yjoca3StqmQcSfkmD7nQ61AqAHL1YgpSQWqHE+HjfGGiHDYKG7PvE33Ku2GyA7lEIJAw==} + '@aws-sdk/credential-provider-node@3.943.0': + resolution: {integrity: sha512-14eddaH/gjCWoLSAELVrFOQNyswUYwWphIt+PdsJ/FqVfP4ay2HsiZVEIYbQtmrKHaoLJhiZKwBQRjcqJDZG0w==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-process@3.936.0': - resolution: {integrity: sha512-GpA4AcHb96KQK2PSPUyvChvrsEKiLhQ5NWjeef2IZ3Jc8JoosiedYqp6yhZR+S8cTysuvx56WyJIJc8y8OTrLA==} + '@aws-sdk/credential-provider-process@3.943.0': + resolution: {integrity: sha512-GIY/vUkthL33AdjOJ8r9vOosKf/3X+X7LIiACzGxvZZrtoOiRq0LADppdiKIB48vTL63VvW+eRIOFAxE6UDekw==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-sso@3.936.0': - resolution: {integrity: sha512-wHlEAJJvtnSyxTfNhN98JcU4taA1ED2JvuI2eePgawqBwS/Tzi0mhED1lvNIaWOkjfLd+nHALwszGrtJwEq4yQ==} + '@aws-sdk/credential-provider-sso@3.943.0': + resolution: {integrity: sha512-1c5G11syUrru3D9OO6Uk+ul5e2lX1adb+7zQNyluNaLPXP6Dina6Sy6DFGRLu7tM8+M7luYmbS3w63rpYpaL+A==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-web-identity@3.936.0': - resolution: {integrity: sha512-v3qHAuoODkoRXsAF4RG+ZVO6q2P9yYBT4GMpMEfU9wXVNn7AIfwZgTwzSUfnjNiGva5BKleWVpRpJ9DeuLFbUg==} + '@aws-sdk/credential-provider-web-identity@3.943.0': + resolution: {integrity: sha512-VtyGKHxICSb4kKGuaqotxso8JVM8RjCS3UYdIMOxUt9TaFE/CZIfZKtjTr+IJ7M0P7t36wuSUb/jRLyNmGzUUA==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-providers@3.936.0': - resolution: {integrity: sha512-RWiX6wuReeEU7/P7apGwWMNO7nrai/CXmMMaho3+pJW7i6ImosgsjSe5tetdv1r4djOtM1b4J4WAbHPKJUahUg==} + '@aws-sdk/credential-providers@3.943.0': + resolution: {integrity: sha512-uZurSNsS01ehhrSwEPwcKdqp9lmd/x9q++BYO351bXyjSj1LzA/2lfUIxI2tCz/wAjJWOdnnlUdJj6P9I1uNvw==} engines: {node: '>=18.0.0'} '@aws-sdk/eventstream-handler-node@3.936.0': @@ -1426,24 +1423,24 @@ packages: resolution: {integrity: sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-user-agent@3.936.0': - resolution: {integrity: sha512-YB40IPa7K3iaYX0lSnV9easDOLPLh+fJyUDF3BH8doX4i1AOSsYn86L4lVldmOaSX+DwiaqKHpvk4wPBdcIPWw==} + '@aws-sdk/middleware-user-agent@3.943.0': + resolution: {integrity: sha512-956n4kVEwFNXndXfhSAN5wO+KRgqiWEEY+ECwLvxmmO8uQ0NWOa8l6l65nTtyuiWzMX81c9BvlyNR5EgUeeUvA==} engines: {node: '>=18.0.0'} '@aws-sdk/middleware-websocket@3.936.0': resolution: {integrity: sha512-bPe3rqeugyj/MmjP0yBSZox2v1Wa8Dv39KN+RxVbQroLO8VUitBo6xyZ0oZebhZ5sASwSg58aDcMlX0uFLQnTA==} engines: {node: '>= 14.0.0'} - '@aws-sdk/nested-clients@3.936.0': - resolution: {integrity: sha512-eyj2tz1XmDSLSZQ5xnB7cLTVKkSJnYAEoNDSUNhzWPxrBDYeJzIbatecOKceKCU8NBf8gWWZCK/CSY0mDxMO0A==} + '@aws-sdk/nested-clients@3.943.0': + resolution: {integrity: sha512-anFtB0p2FPuyUnbOULwGmKYqYKSq1M73c9uZ08jR/NCq6Trjq9cuF5TFTeHwjJyPRb4wMf2Qk859oiVfFqnQiw==} engines: {node: '>=18.0.0'} '@aws-sdk/region-config-resolver@3.936.0': resolution: {integrity: sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==} engines: {node: '>=18.0.0'} - '@aws-sdk/token-providers@3.936.0': - resolution: {integrity: sha512-vvw8+VXk0I+IsoxZw0mX9TMJawUJvEsg3EF7zcCSetwhNPAU8Xmlhv7E/sN/FgSmm7b7DsqKoW6rVtQiCs1PWQ==} + '@aws-sdk/token-providers@3.943.0': + resolution: {integrity: sha512-cRKyIzwfkS+XztXIFPoWORuaxlIswP+a83BJzelX4S1gUZ7FcXB4+lj9Jxjn8SbQhR4TPU3Owbpu+S7pd6IRbQ==} engines: {node: '>=18.0.0'} '@aws-sdk/types@3.936.0': @@ -1465,8 +1462,8 @@ packages: '@aws-sdk/util-user-agent-browser@3.936.0': resolution: {integrity: sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==} - '@aws-sdk/util-user-agent-node@3.936.0': - resolution: {integrity: sha512-XOEc7PF9Op00pWV2AYCGDSu5iHgYjIO53Py2VUQTIvP7SRCaCsXmA33mjBvC2Ms6FhSyWNa4aK4naUGIz0hQcw==} + '@aws-sdk/util-user-agent-node@3.943.0': + resolution: {integrity: sha512-gn+ILprVRrgAgTIBk2TDsJLRClzIOdStQFeFTcN0qpL8Z4GBCqMFhw7O7X+MM55Stt5s4jAauQ/VvoqmCADnQg==} engines: {node: '>=18.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -1481,8 +1478,8 @@ packages: resolution: {integrity: sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==} engines: {node: '>=18.0.0'} - '@aws/lambda-invoke-store@0.2.1': - resolution: {integrity: sha512-sIyFcoPZkTtNu9xFeEoynMef3bPJIAbOfUh+ueYcfhVl6xm2VRtMcMclSxmZCMnHHd4hlYKJeq/aggmBEWynww==} + '@aws/lambda-invoke-store@0.2.2': + resolution: {integrity: sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==} engines: {node: '>=18.0.0'} '@azure/abort-controller@2.1.2': @@ -1622,8 +1619,8 @@ packages: '@braintree/sanitize-url@7.1.1': resolution: {integrity: sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw==} - '@changesets/apply-release-plan@7.0.13': - resolution: {integrity: sha512-BIW7bofD2yAWoE8H4V40FikC+1nNFEKBisMECccS16W1rt6qqhNTBDmIw5HaqmMgtLNz9e7oiALiEUuKrQ4oHg==} + '@changesets/apply-release-plan@7.0.14': + resolution: {integrity: sha512-ddBvf9PHdy2YY0OUiEl3TV78mH9sckndJR14QAt87KLEbIov81XO0q0QAmvooBxXlqRRP8I9B7XOzZwQG7JkWA==} '@changesets/assemble-release-plan@6.0.9': resolution: {integrity: sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==} @@ -1631,12 +1628,12 @@ packages: '@changesets/changelog-git@0.2.1': resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} - '@changesets/cli@2.29.7': - resolution: {integrity: sha512-R7RqWoaksyyKXbKXBTbT4REdy22yH81mcFK6sWtqSanxUCbUi9Uf+6aqxZtDQouIqPdem2W56CdxXgsxdq7FLQ==} + '@changesets/cli@2.29.8': + resolution: {integrity: sha512-1weuGZpP63YWUYjay/E84qqwcnt5yJMM0tep10Up7Q5cS/DGe2IZ0Uj3HNMxGhCINZuR7aO9WBMdKnPit5ZDPA==} hasBin: true - '@changesets/config@3.1.1': - resolution: {integrity: sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==} + '@changesets/config@3.1.2': + resolution: {integrity: sha512-CYiRhA4bWKemdYi/uwImjPxqWNpqGPNbEBdX1BdONALFIDK7MCUj6FPkzD+z9gJcvDFUQJn9aDVf4UG7OT6Kog==} '@changesets/errors@0.2.0': resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} @@ -1644,8 +1641,8 @@ packages: '@changesets/get-dependents-graph@2.1.3': resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} - '@changesets/get-release-plan@4.0.13': - resolution: {integrity: sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg==} + '@changesets/get-release-plan@4.0.14': + resolution: {integrity: sha512-yjZMHpUHgl4Xl5gRlolVuxDkm4HgSJqT93Ri1Uz8kGrQb+5iJ8dkXJ20M2j/Y4iV5QzS2c5SeTxVSKX+2eMI0g==} '@changesets/get-version-range-type@0.4.0': resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} @@ -1656,14 +1653,14 @@ packages: '@changesets/logger@0.1.1': resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} - '@changesets/parse@0.4.1': - resolution: {integrity: sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==} + '@changesets/parse@0.4.2': + resolution: {integrity: sha512-Uo5MC5mfg4OM0jU3up66fmSn6/NE9INK+8/Vn/7sMVcdWg46zfbvvUSjD9EMonVqPi9fbrJH9SXHn48Tr1f2yA==} '@changesets/pre@2.0.2': resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} - '@changesets/read@0.6.5': - resolution: {integrity: sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg==} + '@changesets/read@0.6.6': + resolution: {integrity: sha512-P5QaN9hJSQQKJShzzpBT13FzOSPyHbqdoIBUd2DJdgvnECCyO6LmAOWSV+O8se2TaZJVwSXjL+v9yhb+a9JeJg==} '@changesets/should-skip-package@0.1.2': resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} @@ -1762,158 +1759,158 @@ packages: resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==} deprecated: 'Merged into tsx: https://tsx.is' - '@esbuild/aix-ppc64@0.27.0': - resolution: {integrity: sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==} + '@esbuild/aix-ppc64@0.27.1': + resolution: {integrity: sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.27.0': - resolution: {integrity: sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==} + '@esbuild/android-arm64@0.27.1': + resolution: {integrity: sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.27.0': - resolution: {integrity: sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==} + '@esbuild/android-arm@0.27.1': + resolution: {integrity: sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.27.0': - resolution: {integrity: sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==} + '@esbuild/android-x64@0.27.1': + resolution: {integrity: sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.27.0': - resolution: {integrity: sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==} + '@esbuild/darwin-arm64@0.27.1': + resolution: {integrity: sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.27.0': - resolution: {integrity: sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==} + '@esbuild/darwin-x64@0.27.1': + resolution: {integrity: sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.27.0': - resolution: {integrity: sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==} + '@esbuild/freebsd-arm64@0.27.1': + resolution: {integrity: sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.0': - resolution: {integrity: sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==} + '@esbuild/freebsd-x64@0.27.1': + resolution: {integrity: sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.27.0': - resolution: {integrity: sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==} + '@esbuild/linux-arm64@0.27.1': + resolution: {integrity: sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.27.0': - resolution: {integrity: sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==} + '@esbuild/linux-arm@0.27.1': + resolution: {integrity: sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.27.0': - resolution: {integrity: sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==} + '@esbuild/linux-ia32@0.27.1': + resolution: {integrity: sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.27.0': - resolution: {integrity: sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==} + '@esbuild/linux-loong64@0.27.1': + resolution: {integrity: sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.27.0': - resolution: {integrity: sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==} + '@esbuild/linux-mips64el@0.27.1': + resolution: {integrity: sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.27.0': - resolution: {integrity: sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==} + '@esbuild/linux-ppc64@0.27.1': + resolution: {integrity: sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.27.0': - resolution: {integrity: sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==} + '@esbuild/linux-riscv64@0.27.1': + resolution: {integrity: sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.27.0': - resolution: {integrity: sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==} + '@esbuild/linux-s390x@0.27.1': + resolution: {integrity: sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.27.0': - resolution: {integrity: sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==} + '@esbuild/linux-x64@0.27.1': + resolution: {integrity: sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.27.0': - resolution: {integrity: sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==} + '@esbuild/netbsd-arm64@0.27.1': + resolution: {integrity: sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.0': - resolution: {integrity: sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==} + '@esbuild/netbsd-x64@0.27.1': + resolution: {integrity: sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.27.0': - resolution: {integrity: sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==} + '@esbuild/openbsd-arm64@0.27.1': + resolution: {integrity: sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.0': - resolution: {integrity: sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==} + '@esbuild/openbsd-x64@0.27.1': + resolution: {integrity: sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.27.0': - resolution: {integrity: sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==} + '@esbuild/openharmony-arm64@0.27.1': + resolution: {integrity: sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.27.0': - resolution: {integrity: sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==} + '@esbuild/sunos-x64@0.27.1': + resolution: {integrity: sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.27.0': - resolution: {integrity: sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==} + '@esbuild/win32-arm64@0.27.1': + resolution: {integrity: sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.27.0': - resolution: {integrity: sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==} + '@esbuild/win32-ia32@0.27.1': + resolution: {integrity: sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.27.0': - resolution: {integrity: sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==} + '@esbuild/win32-x64@0.27.1': + resolution: {integrity: sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -1940,8 +1937,8 @@ packages: resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@3.3.1': - resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + '@eslint/eslintrc@3.3.3': + resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/js@9.39.1': @@ -1977,8 +1974,8 @@ packages: '@floating-ui/utils@0.2.10': resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} - '@google/genai@1.30.0': - resolution: {integrity: sha512-3MRcgczBFbUat1wIlZoLJ0vCCfXgm7Qxjh59cZi2X08RgWLtm9hKOspzp7TOg1TV2e26/MLxR2GR5yD5GmBV2w==} + '@google/genai@1.31.0': + resolution: {integrity: sha512-rK0RKXxNkbK35eDl+G651SxtxwHNEOogjyeZJUJe+Ed4yxu3xy5ufCiU0+QLT7xo4M9Spey8OAYfD8LPRlYBKw==} engines: {node: '>=20.0.0'} peerDependencies: '@modelcontextprotocol/sdk': ^1.20.1 @@ -2010,142 +2007,110 @@ packages: '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} - '@iconify/utils@3.0.2': - resolution: {integrity: sha512-EfJS0rLfVuRuJRn4psJHtK2A9TqVnkxPpHY6lYHiB9+8eSuudsxbwMiavocG45ujOo6FJ+CIRlRnlOGinzkaGQ==} - - '@img/colour@1.0.0': - resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} - engines: {node: '>=18'} + '@iconify/utils@3.1.0': + resolution: {integrity: sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==} - '@img/sharp-darwin-arm64@0.34.5': - resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + '@img/sharp-darwin-arm64@0.33.5': + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [darwin] - '@img/sharp-darwin-x64@0.34.5': - resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + '@img/sharp-darwin-x64@0.33.5': + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [darwin] - '@img/sharp-libvips-darwin-arm64@1.2.4': - resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + '@img/sharp-libvips-darwin-arm64@1.0.4': + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} cpu: [arm64] os: [darwin] - '@img/sharp-libvips-darwin-x64@1.2.4': - resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + '@img/sharp-libvips-darwin-x64@1.0.4': + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} cpu: [x64] os: [darwin] - '@img/sharp-libvips-linux-arm64@1.2.4': - resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + '@img/sharp-libvips-linux-arm64@1.0.4': + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} cpu: [arm64] os: [linux] - '@img/sharp-libvips-linux-arm@1.2.4': - resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + '@img/sharp-libvips-linux-arm@1.0.5': + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} cpu: [arm] os: [linux] - '@img/sharp-libvips-linux-ppc64@1.2.4': - resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} - cpu: [ppc64] - os: [linux] - - '@img/sharp-libvips-linux-riscv64@1.2.4': - resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} - cpu: [riscv64] - os: [linux] - - '@img/sharp-libvips-linux-s390x@1.2.4': - resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + '@img/sharp-libvips-linux-s390x@1.0.4': + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} cpu: [s390x] os: [linux] - '@img/sharp-libvips-linux-x64@1.2.4': - resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + '@img/sharp-libvips-linux-x64@1.0.4': + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} cpu: [x64] os: [linux] - '@img/sharp-libvips-linuxmusl-arm64@1.2.4': - resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} cpu: [arm64] os: [linux] - '@img/sharp-libvips-linuxmusl-x64@1.2.4': - resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} cpu: [x64] os: [linux] - '@img/sharp-linux-arm64@0.34.5': - resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + '@img/sharp-linux-arm64@0.33.5': + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - '@img/sharp-linux-arm@0.34.5': - resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + '@img/sharp-linux-arm@0.33.5': + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] - '@img/sharp-linux-ppc64@0.34.5': - resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [ppc64] - os: [linux] - - '@img/sharp-linux-riscv64@0.34.5': - resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [riscv64] - os: [linux] - - '@img/sharp-linux-s390x@0.34.5': - resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} + '@img/sharp-linux-s390x@0.33.5': + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] - '@img/sharp-linux-x64@0.34.5': - resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + '@img/sharp-linux-x64@0.33.5': + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - '@img/sharp-linuxmusl-arm64@0.34.5': - resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + '@img/sharp-linuxmusl-arm64@0.33.5': + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - '@img/sharp-linuxmusl-x64@0.34.5': - resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + '@img/sharp-linuxmusl-x64@0.33.5': + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - '@img/sharp-wasm32@0.34.5': - resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} + '@img/sharp-wasm32@0.33.5': + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [wasm32] - '@img/sharp-win32-arm64@0.34.5': - resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [win32] - - '@img/sharp-win32-ia32@0.34.5': - resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + '@img/sharp-win32-ia32@0.33.5': + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ia32] os: [win32] - '@img/sharp-win32-x64@0.34.5': - resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + '@img/sharp-win32-x64@0.33.5': + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [win32] @@ -2247,11 +2212,12 @@ packages: '@mixmark-io/domino@2.2.0': resolution: {integrity: sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==} - '@modelcontextprotocol/sdk@1.22.0': - resolution: {integrity: sha512-VUpl106XVTCpDmTBil2ehgJZjhyLY2QZikzF8NvTXtLRF1CvO5iEE2UNZdVIUer35vFOwMKYeUGbjJtvPWan3g==} + '@modelcontextprotocol/sdk@1.24.2': + resolution: {integrity: sha512-hS/kzSfchqzvUeJUsdiDHi84/kNhLIZaZ6coGQVwbYIelOBbcAwUohUfaQTLa1MvFOK/jbTnGFzraHSFwB7pjQ==} engines: {node: '>=18'} peerDependencies: '@cfworker/json-schema': ^4.1.1 + zod: ^3.25 || ^4.0 peerDependenciesMeta: '@cfworker/json-schema': optional: true @@ -2263,62 +2229,62 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} - '@napi-rs/wasm-runtime@1.0.7': - resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} + '@napi-rs/wasm-runtime@1.1.0': + resolution: {integrity: sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA==} '@next/env@13.5.11': resolution: {integrity: sha512-fbb2C7HChgM7CemdCY+y3N1n8pcTKdqtQLbC7/EQtPdLvlMUT9JX/dBYl8MMZAtYG4uVMyPFHXckb68q/NRwqg==} - '@next/env@15.5.6': - resolution: {integrity: sha512-3qBGRW+sCGzgbpc5TS1a0p7eNxnOarGVQhZxfvTdnV0gFI61lX7QNtQ4V1TSREctXzYn5NetbUsLvyqwLFJM6Q==} + '@next/env@15.2.6': + resolution: {integrity: sha512-kp1Mpm4K1IzSSJ5ZALfek0JBD2jBw9VGMXR/aT7ykcA2q/ieDARyBzg+e8J1TkeIb5AFj/YjtZdoajdy5uNy6w==} - '@next/eslint-plugin-next@15.5.6': - resolution: {integrity: sha512-YxDvsT2fwy1j5gMqk3ppXlsgDopHnkM4BoxSVASbvvgh5zgsK8lvWerDzPip8k3WVzsTZ1O7A7si1KNfN4OZfQ==} + '@next/eslint-plugin-next@15.5.7': + resolution: {integrity: sha512-DtRU2N7BkGr8r+pExfuWHwMEPX5SD57FeA6pxdgCHODo+b/UgIgjE+rgWKtJAbEbGhVZ2jtHn4g3wNhWFoNBQQ==} - '@next/swc-darwin-arm64@15.5.6': - resolution: {integrity: sha512-ES3nRz7N+L5Umz4KoGfZ4XX6gwHplwPhioVRc25+QNsDa7RtUF/z8wJcbuQ2Tffm5RZwuN2A063eapoJ1u4nPg==} + '@next/swc-darwin-arm64@15.2.5': + resolution: {integrity: sha512-4OimvVlFTbgzPdA0kh8A1ih6FN9pQkL4nPXGqemEYgk+e7eQhsst/p35siNNqA49eQA6bvKZ1ASsDtu9gtXuog==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.5.6': - resolution: {integrity: sha512-JIGcytAyk9LQp2/nuVZPAtj8uaJ/zZhsKOASTjxDug0SPU9LAM3wy6nPU735M1OqacR4U20LHVF5v5Wnl9ptTA==} + '@next/swc-darwin-x64@15.2.5': + resolution: {integrity: sha512-ohzRaE9YbGt1ctE0um+UGYIDkkOxHV44kEcHzLqQigoRLaiMtZzGrA11AJh2Lu0lv51XeiY1ZkUvkThjkVNBMA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.5.6': - resolution: {integrity: sha512-qvz4SVKQ0P3/Im9zcS2RmfFL/UCQnsJKJwQSkissbngnB/12c6bZTCB0gHTexz1s6d/mD0+egPKXAIRFVS7hQg==} + '@next/swc-linux-arm64-gnu@15.2.5': + resolution: {integrity: sha512-FMSdxSUt5bVXqqOoZCc/Seg4LQep9w/fXTazr/EkpXW2Eu4IFI9FD7zBDlID8TJIybmvKk7mhd9s+2XWxz4flA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.5.6': - resolution: {integrity: sha512-FsbGVw3SJz1hZlvnWD+T6GFgV9/NYDeLTNQB2MXoPN5u9VA9OEDy6fJEfePfsUKAhJufFbZLgp0cPxMuV6SV0w==} + '@next/swc-linux-arm64-musl@15.2.5': + resolution: {integrity: sha512-4ZNKmuEiW5hRKkGp2HWwZ+JrvK4DQLgf8YDaqtZyn7NYdl0cHfatvlnLFSWUayx9yFAUagIgRGRk8pFxS8Qniw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.5.6': - resolution: {integrity: sha512-3QnHGFWlnvAgyxFxt2Ny8PTpXtQD7kVEeaFat5oPAHHI192WKYB+VIKZijtHLGdBBvc16tiAkPTDmQNOQ0dyrA==} + '@next/swc-linux-x64-gnu@15.2.5': + resolution: {integrity: sha512-bE6lHQ9GXIf3gCDE53u2pTl99RPZW5V1GLHSRMJ5l/oB/MT+cohu9uwnCK7QUph2xIOu2a6+27kL0REa/kqwZw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.5.6': - resolution: {integrity: sha512-OsGX148sL+TqMK9YFaPFPoIaJKbFJJxFzkXZljIgA9hjMjdruKht6xDCEv1HLtlLNfkx3c5w2GLKhj7veBQizQ==} + '@next/swc-linux-x64-musl@15.2.5': + resolution: {integrity: sha512-y7EeQuSkQbTAkCEQnJXm1asRUuGSWAchGJ3c+Qtxh8LVjXleZast8Mn/rL7tZOm7o35QeIpIcid6ufG7EVTTcA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.5.6': - resolution: {integrity: sha512-ONOMrqWxdzXDJNh2n60H6gGyKed42Ieu6UTVPZteXpuKbLZTH4G4eBMsr5qWgOBA+s7F+uB4OJbZnrkEDnZ5Fg==} + '@next/swc-win32-arm64-msvc@15.2.5': + resolution: {integrity: sha512-gQMz0yA8/dskZM2Xyiq2FRShxSrsJNha40Ob/M2n2+JGRrZ0JwTVjLdvtN6vCxuq4ByhOd4a9qEf60hApNR2gQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.5.6': - resolution: {integrity: sha512-pxK4VIjFRx1MY92UycLOOw7dTdvccWsNETQ0kDHkBlcFH1GrTLUjSiHU1ohrznnux6TqRHgv5oflhfIWZwVROQ==} + '@next/swc-win32-x64-msvc@15.2.5': + resolution: {integrity: sha512-tBDNVUcI7U03+3oMvJ11zrtVin5p0NctiuKmTGyaTIEAVj9Q77xukLXGXRnWxKRIIdFG4OTA2rUVGZDYOwgmAA==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -2447,109 +2413,114 @@ packages: resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} engines: {node: '>=8.0.0'} - '@oxc-resolver/binding-android-arm-eabi@11.13.2': - resolution: {integrity: sha512-vWd1NEaclg/t2DtEmYzRRBNQOueMI8tixw/fSNZ9XETXLRJiAjQMYpYeflQdRASloGze6ZelHE/wIBNt4S+pkw==} + '@oxc-resolver/binding-android-arm-eabi@11.14.2': + resolution: {integrity: sha512-bTrdE4Z1JcGwPxBOaGbxRbpOHL8/xPVJTTq3/bAZO2euWX0X7uZ+XxsbC+5jUDMhLenqdFokgE1akHEU4xsh6A==} cpu: [arm] os: [android] - '@oxc-resolver/binding-android-arm64@11.13.2': - resolution: {integrity: sha512-jxZrYcxgpI6IuQpguQVAQNrZfUyiYfMVqR4pKVU3PRLCM7AsfXNKp0TIgcvp+l6dYVdoZ1MMMMa5Ayjd09rNOw==} + '@oxc-resolver/binding-android-arm64@11.14.2': + resolution: {integrity: sha512-bL7/f6YGKUvt/wzpX7ZrHCf1QerotbSG+IIb278AklXuwr6yQdfQHt7KQ8hAWqSYpB2TAbPbAa9HE4wzVyxL9Q==} cpu: [arm64] os: [android] - '@oxc-resolver/binding-darwin-arm64@11.13.2': - resolution: {integrity: sha512-RDS3HUe1FvgjNS1xfBUqiEJ8938Zb5r7iKABwxEblp3K4ufZZNAtoaHjdUH2TJ0THDmuf0OxxVUO/Y+4Ep4QfQ==} + '@oxc-resolver/binding-darwin-arm64@11.14.2': + resolution: {integrity: sha512-0zhMhqHz/kC6/UzMC4D9mVBz3/M9UTorbaULfHjAW5b8SUC08H01lZ5fR3OzfDbJI0ByLfiQZmbovuR/pJ8Wzg==} cpu: [arm64] os: [darwin] - '@oxc-resolver/binding-darwin-x64@11.13.2': - resolution: {integrity: sha512-tDcyWtkUzkt6auJLP2dOjL84BxqHkKW4mz2lNRIGPTq7b+HBraB+m8RdRH6BgqTvbnNECOxR3XAMaKBKC8J51g==} + '@oxc-resolver/binding-darwin-x64@11.14.2': + resolution: {integrity: sha512-kRJBTCQnrGy1mjO+658yMrlGYWEKi6j4JvKt92PRCoeDX0vW4jvzgoJXzZXNxZL1pCY6jIdwsn9u53v4jwpR6g==} cpu: [x64] os: [darwin] - '@oxc-resolver/binding-freebsd-x64@11.13.2': - resolution: {integrity: sha512-fpaeN8Q0kWvKns9uSMg6CcKo7cdgmWt6J91stPf8sdM+EKXzZ0YcRnWWyWF8SM16QcLUPCy5Iwt5Z8aYBGaZYA==} + '@oxc-resolver/binding-freebsd-x64@11.14.2': + resolution: {integrity: sha512-lpKiya7qPq5EAV5E16SJbxfhNYRCBZATGngn9mZxR2fMLDVbHISDIP2Br8eWA8M1FBJFsOGgBzxDo+42ySSNZQ==} cpu: [x64] os: [freebsd] - '@oxc-resolver/binding-linux-arm-gnueabihf@11.13.2': - resolution: {integrity: sha512-idBgJU5AvSsGOeaIWiFBKbNBjpuduHsJmrG4CBbEUNW/Ykx+ISzcuj1PHayiYX6R9stVsRhj3d2PyymfC5KWRg==} + '@oxc-resolver/binding-linux-arm-gnueabihf@11.14.2': + resolution: {integrity: sha512-zRIf49IGs4cE9rwpVM3NxlHWquZpwQLebtc9dY9S+4+B+PSLIP95BrzdRfkspwzWC5DKZsOWpvGQjxQiLoUwGA==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm-musleabihf@11.13.2': - resolution: {integrity: sha512-BlBvQUhvvIM/7s96KlKhMk0duR2sj8T7Hyii46/5QnwfN/pHwobvOL5czZ6/SKrHNB/F/qDY4hGsBuB1y7xgTg==} + '@oxc-resolver/binding-linux-arm-musleabihf@11.14.2': + resolution: {integrity: sha512-sF1fBrcfwoRkv1pR3Kp6D5MuBeHRPxYuzk9rhaun/50vq5nAMOaomkEm4hBbTSubfU86CoBIEbLUQ+1f7NvUVA==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm64-gnu@11.13.2': - resolution: {integrity: sha512-lUmDTmYOGpbIK+FBfZ0ySaQTo7g1Ia/WnDnQR2wi/0AtehZIg/ZZIgiT/fD0iRvKEKma612/0PVo8dXdAKaAGA==} + '@oxc-resolver/binding-linux-arm64-gnu@11.14.2': + resolution: {integrity: sha512-O8iTBqz6oxf1k93Rn6WMGGQYo2jV1K81hq4N/Nke3dHE25EIEg2RKQqMz1dFrvVb2RkvD7QaUTEevbx0Lq+4wQ==} cpu: [arm64] os: [linux] - '@oxc-resolver/binding-linux-arm64-musl@11.13.2': - resolution: {integrity: sha512-dkGzOxo+I9lA4Er6qzFgkFevl3JvwyI9i0T/PkOJHva04rb1p9dz8GPogTO9uMK4lrwLWzm/piAu+tHYC7v7+w==} + '@oxc-resolver/binding-linux-arm64-musl@11.14.2': + resolution: {integrity: sha512-HOfzpS6eUxvdch9UlXCMx2kNJWMNBjUpVJhseqAKDB1dlrfCHgexeLyBX977GLXkq2BtNXKsY3KCryy1QhRSRw==} cpu: [arm64] os: [linux] - '@oxc-resolver/binding-linux-ppc64-gnu@11.13.2': - resolution: {integrity: sha512-53kWsjLkVFnoSA7COdps38pBssN48zI8LfsOvupsmQ0/4VeMYb+0Ao9O6r52PtmFZsGB3S1Qjqbjl/Pswj1a3g==} + '@oxc-resolver/binding-linux-ppc64-gnu@11.14.2': + resolution: {integrity: sha512-0uLG6F2zljUseQAUmlpx/9IdKpiLsSirpmrr8/aGVfiEurIJzC/1lo2HQskkM7e0VVOkXg37AjHUDLE23Fi8SA==} cpu: [ppc64] os: [linux] - '@oxc-resolver/binding-linux-riscv64-gnu@11.13.2': - resolution: {integrity: sha512-MfxN6DMpvmdCbGlheJ+ihy11oTcipqDfcEIQV9ah3FGXBRCZtBOHJpQDk8qI2Y+nCXVr3Nln7OSsOzoC4+rSYQ==} + '@oxc-resolver/binding-linux-riscv64-gnu@11.14.2': + resolution: {integrity: sha512-Pdh0BH/E0YIK7Qg95IsAfQyU9rAoDoFh50R19zCTNfjSnwsoDMGHjmUc82udSfPo2YMnuxA+/+aglxmLQVSu2Q==} cpu: [riscv64] os: [linux] - '@oxc-resolver/binding-linux-riscv64-musl@11.13.2': - resolution: {integrity: sha512-WXrm4YiRU0ijqb72WHSjmfYaQZ7t6/kkQrFc4JtU+pUE4DZA/DEdxOuQEd4Q43VqmLvICTJWSaZMlCGQ4PSRUg==} + '@oxc-resolver/binding-linux-riscv64-musl@11.14.2': + resolution: {integrity: sha512-3DLQhJ2r53rCH5cudYFqD7nh+Z6ABvld3GjbiqHhT43GMIPw3JcHekC2QunLRNjRr1G544fo1HtjTJz9rCBpyg==} cpu: [riscv64] os: [linux] - '@oxc-resolver/binding-linux-s390x-gnu@11.13.2': - resolution: {integrity: sha512-4pISWIlOFRUhWyvGCB3XUhtcwyvwGGhlXhHz7IXCXuGufaQtvR05trvw8U1ZnaPhsdPBkRhOMIedX11ayi5uXw==} + '@oxc-resolver/binding-linux-s390x-gnu@11.14.2': + resolution: {integrity: sha512-G5BnAOQ5f+RUG1cvlJ4BvV+P7iKLYBv67snqgcfwD5b2N4UwJj32bt4H5JfolocWy4x3qUjEDWTIjHdE+2uZ9w==} cpu: [s390x] os: [linux] - '@oxc-resolver/binding-linux-x64-gnu@11.13.2': - resolution: {integrity: sha512-DVo6jS8n73yNAmCsUOOk2vBeC60j2RauDXQM8p7RDl0afsEaA2le22vD8tky7iNoM5tsxfBmE4sOJXEKgpwWRw==} + '@oxc-resolver/binding-linux-x64-gnu@11.14.2': + resolution: {integrity: sha512-VirQAX2PqKrhWtQGsSDEKlPhbgh3ggjT1sWuxLk4iLFwtyA2tLEPXJNAsG0kfAS2+VSA8OyNq16wRpQlMPZ4yA==} cpu: [x64] os: [linux] - '@oxc-resolver/binding-linux-x64-musl@11.13.2': - resolution: {integrity: sha512-6WqrE+hQBFP35KdwQjWcZpldbTq6yJmuTVThISu+rY3+j6MaDp2ciLHTr1X68r2H/7ocOIl4k3NnOVIzeRJE3w==} + '@oxc-resolver/binding-linux-x64-musl@11.14.2': + resolution: {integrity: sha512-q4ORcwMkpzu4EhZyka/s2TuH2QklEHAr/mIQBXzu5BACeBJZIFkICp8qrq4XVnkEZ+XhSFTvBECqfMTT/4LSkA==} cpu: [x64] os: [linux] - '@oxc-resolver/binding-wasm32-wasi@11.13.2': - resolution: {integrity: sha512-YpxvQmP2D+mNUkLQZbBjGz20g/pY8XoOBdPPoWMl9X68liFFjXxkPQTrZxWw4zzG/UkTM5z6dPRTyTePRsMcjw==} + '@oxc-resolver/binding-openharmony-arm64@11.14.2': + resolution: {integrity: sha512-ZsMIpDCxSFpUM/TwOovX5vZUkV0IukPFnrKTGaeJRuTKXMcJxMiQGCYTwd6y684Y3j55QZqIMkVM9NdCGUX6Kw==} + cpu: [arm64] + os: [openharmony] + + '@oxc-resolver/binding-wasm32-wasi@11.14.2': + resolution: {integrity: sha512-Lvq5ZZNvSjT3Jq/buPFMtp55eNyGlEWsq30tN+yLOfODSo6T6yAJNs6+wXtqu9PiMj4xpVtgXypHtbQ1f+t7kw==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@oxc-resolver/binding-win32-arm64-msvc@11.13.2': - resolution: {integrity: sha512-1SKBw6KcCmvPBdEw1/Qdpv6eSDf23lCXTWz9VxTe6QUQ/1wR+HZR2uS4q6C8W6jnIswMTQbxpTvVwdRXl+ufeA==} + '@oxc-resolver/binding-win32-arm64-msvc@11.14.2': + resolution: {integrity: sha512-7w7WHSLSSmkkYHH52QF7TrO0Z8eaIjRUrre5M56hSWRAZupCRzADZxBVMpDnHobZ8MAa2kvvDEfDbERuOK/avQ==} cpu: [arm64] os: [win32] - '@oxc-resolver/binding-win32-ia32-msvc@11.13.2': - resolution: {integrity: sha512-KEVV7wggDucxRn3vvyHnmTCPXoCT7vWpH18UVLTygibHJvNRP2zl5lBaQcCIdIaYYZjKt1aGI/yZqxZvHoiCdg==} + '@oxc-resolver/binding-win32-ia32-msvc@11.14.2': + resolution: {integrity: sha512-hIrdlWa6tzqyfuWrxUetURBWHttBS+NMbBrGhCupc54NCXFy2ArB+0JOOaLYiI2ShKL5a3uqB7EWxmjzOuDdPQ==} cpu: [ia32] os: [win32] - '@oxc-resolver/binding-win32-x64-msvc@11.13.2': - resolution: {integrity: sha512-6AAdN9v/wO5c3td1yidgNLKYlzuNgfOtEqBq60WE469bJWR7gHgG/S5aLR2pH6/gyPLs9UXtItxi934D+0Estg==} + '@oxc-resolver/binding-win32-x64-msvc@11.14.2': + resolution: {integrity: sha512-dP9aV6AZRRpg5mlg0eMuTROtttpQwj3AiegNJ/NNmMSjs+0+aLNcgkWRPhskK3vjTsthH4/+kKLpnQhSxdJkNg==} cpu: [x64] os: [win32] '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} - '@posthog/core@1.5.5': - resolution: {integrity: sha512-m7G1EQTgo9xrr3lZxCp9C2egP99MSRpIDD95wYzwUPxMesKxI0xEQ+TC5LS/XOXIdmsNvsx4UcxwmzhSwD2GWA==} + '@posthog/core@1.7.0': + resolution: {integrity: sha512-d6ZV4grpzeH/6/LP8quMVpSjY1puRkrqfwcPvGRKUAX7tb7YHyp/zMiTDuJmOFbpUxAMBXH5nDwcPiyCY2WGzA==} - '@puppeteer/browsers@2.10.13': - resolution: {integrity: sha512-a9Ruw3j3qlnB5a/zHRTkruppynxqaeE4H9WNj5eYGRWqw0ZauZ23f4W2ARf3hghF5doozyD+CRtt7XSYuYRI/Q==} + '@puppeteer/browsers@2.11.0': + resolution: {integrity: sha512-n6oQX6mYkG8TRPuPXmbPidkUbsSRalhmaaVAQxvH1IkQy63cwsH+kOjB3e4cpCDHg0aSvsiX9bQ4s2VB6mGWUQ==} engines: {node: '>=18'} hasBin: true @@ -2558,8 +2529,8 @@ packages: engines: {node: '>=18'} hasBin: true - '@qdrant/js-client-rest@1.16.0': - resolution: {integrity: sha512-Tppb9SzBdfdU2U6u/wizxzIjB/onOOgcCohUrlw0l+aH1ELC/oKEBCCCIW/CrE+G6c+GLr2aatOqZp/Vahiz+A==} + '@qdrant/js-client-rest@1.16.2': + resolution: {integrity: sha512-Zm4wEZURrZ24a+Hmm4l1QQYjiz975Ep3vF0yzWR7ICGcxittNz47YK2iBOk8kb8qseCu8pg7WmO1HOIsO8alvw==} engines: {node: '>=18.17.0', pnpm: '>=8'} peerDependencies: typescript: '>=4.7' @@ -3225,23 +3196,23 @@ packages: '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} - '@shikijs/core@3.15.0': - resolution: {integrity: sha512-8TOG6yG557q+fMsSVa8nkEDOZNTSxjbbR8l6lF2gyr6Np+jrPlslqDxQkN6rMXCECQ3isNPZAGszAfYoJOPGlg==} + '@shikijs/core@3.19.0': + resolution: {integrity: sha512-L7SrRibU7ZoYi1/TrZsJOFAnnHyLTE1SwHG1yNWjZIVCqjOEmCSuK2ZO9thnRbJG6TOkPp+Z963JmpCNw5nzvA==} - '@shikijs/engine-javascript@3.15.0': - resolution: {integrity: sha512-ZedbOFpopibdLmvTz2sJPJgns8Xvyabe2QbmqMTz07kt1pTzfEvKZc5IqPVO/XFiEbbNyaOpjPBkkr1vlwS+qg==} + '@shikijs/engine-javascript@3.19.0': + resolution: {integrity: sha512-ZfWJNm2VMhKkQIKT9qXbs76RRcT0SF/CAvEz0+RkpUDAoDaCx0uFdCGzSRiD9gSlhm6AHkjdieOBJMaO2eC1rQ==} - '@shikijs/engine-oniguruma@3.15.0': - resolution: {integrity: sha512-HnqFsV11skAHvOArMZdLBZZApRSYS4LSztk2K3016Y9VCyZISnlYUYsL2hzlS7tPqKHvNqmI5JSUJZprXloMvA==} + '@shikijs/engine-oniguruma@3.19.0': + resolution: {integrity: sha512-1hRxtYIJfJSZeM5ivbUXv9hcJP3PWRo5prG/V2sWwiubUKTa+7P62d2qxCW8jiVFX4pgRHhnHNp+qeR7Xl+6kg==} - '@shikijs/langs@3.15.0': - resolution: {integrity: sha512-WpRvEFvkVvO65uKYW4Rzxs+IG0gToyM8SARQMtGGsH4GDMNZrr60qdggXrFOsdfOVssG/QQGEl3FnJ3EZ+8w8A==} + '@shikijs/langs@3.19.0': + resolution: {integrity: sha512-dBMFzzg1QiXqCVQ5ONc0z2ebyoi5BKz+MtfByLm0o5/nbUu3Iz8uaTCa5uzGiscQKm7lVShfZHU1+OG3t5hgwg==} - '@shikijs/themes@3.15.0': - resolution: {integrity: sha512-8ow2zWb1IDvCKjYb0KiLNrK4offFdkfNVPXb1OZykpLCzRU6j+efkY+Y7VQjNlNFXonSw+4AOdGYtmqykDbRiQ==} + '@shikijs/themes@3.19.0': + resolution: {integrity: sha512-H36qw+oh91Y0s6OlFfdSuQ0Ld+5CgB/VE6gNPK+Hk4VRbVG/XQgkjnt4KzfnnoO6tZPtKJKHPjwebOCfjd6F8A==} - '@shikijs/types@3.15.0': - resolution: {integrity: sha512-BnP+y/EQnhihgHy4oIAN+6FFtmfTekwOLsQbRw9hOKwqgNy8Bdsjq8B05oAt/ZgvIWWFrshV71ytOrlPfYjIJw==} + '@shikijs/types@3.19.0': + resolution: {integrity: sha512-Z2hdeEQlzuntf/BZpFG8a+Fsw9UVXdML7w0o3TgSXV3yNESGon+bs9ITkQb3Ki7zxoXOOu5oJWqZ2uto06V9iQ==} '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} @@ -3270,8 +3241,8 @@ packages: resolution: {integrity: sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==} engines: {node: '>=18.0.0'} - '@smithy/core@3.18.5': - resolution: {integrity: sha512-6gnIz3h+PEPQGDj8MnRSjDvKBah042jEoPgjFGJ4iJLBE78L4lY/n98x14XyPF4u3lN179Ub/ZKFY5za9GeLQw==} + '@smithy/core@3.18.7': + resolution: {integrity: sha512-axG9MvKhMWOhFbvf5y2DuyTxQueO0dkedY9QC3mAfndLosRI/9LJv8WaL0mw7ubNhsO4IuXX9/9dYGPFvHrqlw==} engines: {node: '>=18.0.0'} '@smithy/credential-provider-imds@4.2.5': @@ -3344,12 +3315,12 @@ packages: resolution: {integrity: sha512-1/8kFp6Fl4OsSIVTWHnNjLnTL8IqpIb/D3sTSczrKFnrE9VMNWxnrRKNvpUHOJ6zpGD5f62TPm7+17ilTJpiCQ==} engines: {node: '>=14.0.0'} - '@smithy/middleware-endpoint@4.3.12': - resolution: {integrity: sha512-9pAX/H+VQPzNbouhDhkW723igBMLgrI8OtX+++M7iKJgg/zY/Ig3i1e6seCcx22FWhE6Q/S61BRdi2wXBORT+A==} + '@smithy/middleware-endpoint@4.3.14': + resolution: {integrity: sha512-v0q4uTKgBM8dsqGjqsabZQyH85nFaTnFcgpWU1uydKFsdyyMzfvOkNum9G7VK+dOP01vUnoZxIeRiJ6uD0kjIg==} engines: {node: '>=18.0.0'} - '@smithy/middleware-retry@4.4.12': - resolution: {integrity: sha512-S4kWNKFowYd0lID7/DBqWHOQxmxlsf0jBaos9chQZUWTVOjSW1Ogyh8/ib5tM+agFDJ/TCxuCTvrnlc+9cIBcQ==} + '@smithy/middleware-retry@4.4.14': + resolution: {integrity: sha512-Z2DG8Ej7FyWG1UA+7HceINtSLzswUgs2np3sZX0YBBxCt+CXG4QUxv88ZDS3+2/1ldW7LqtSY1UO/6VQ1pND8Q==} engines: {node: '>=18.0.0'} '@smithy/middleware-serde@2.3.0': @@ -3440,8 +3411,8 @@ packages: resolution: {integrity: sha512-jrbSQrYCho0yDaaf92qWgd+7nAeap5LtHTI51KXqmpIFCceKU3K9+vIVTUH72bOJngBMqa4kyu1VJhRcSrk/CQ==} engines: {node: '>=14.0.0'} - '@smithy/smithy-client@4.9.8': - resolution: {integrity: sha512-8xgq3LgKDEFoIrLWBho/oYKyWByw9/corz7vuh1upv7ZBm0ZMjGYBhbn6v643WoIqA9UTcx5A5htEp/YatUwMA==} + '@smithy/smithy-client@4.9.10': + resolution: {integrity: sha512-Jaoz4Jw1QYHc1EFww/E6gVtNjhoDU+gwRKqXP6C3LKYqqH2UQhP8tMP3+t/ePrhaze7fhLE8vS2q6vVxBANFTQ==} engines: {node: '>=18.0.0'} '@smithy/types@2.12.0': @@ -3495,12 +3466,12 @@ packages: resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-browser@4.3.11': - resolution: {integrity: sha512-yHv+r6wSQXEXTPVCIQTNmXVWs7ekBTpMVErjqZoWkYN75HIFN5y9+/+sYOejfAuvxWGvgzgxbTHa/oz61YTbKw==} + '@smithy/util-defaults-mode-browser@4.3.13': + resolution: {integrity: sha512-hlVLdAGrVfyNei+pKIgqDTxfu/ZI2NSyqj4IDxKd5bIsIqwR/dSlkxlPaYxFiIaDVrBy0he8orsFy+Cz119XvA==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-node@4.2.14': - resolution: {integrity: sha512-ljZN3iRvaJUgulfvobIuG97q1iUuCMrvXAlkZ4msY+ZuVHQHDIqn7FKZCEj+bx8omz6kF5yQXms/xhzjIO5XiA==} + '@smithy/util-defaults-mode-node@4.2.16': + resolution: {integrity: sha512-F1t22IUiJLHrxW9W1CQ6B9PN+skZ9cqSuzB18Eh06HrJPbjsyZ7ZHecAKw80DQtyGTRcVfeukKaCRYebFwclbg==} engines: {node: '>=18.0.0'} '@smithy/util-endpoints@3.2.5': @@ -3577,6 +3548,9 @@ packages: '@standard-schema/utils@0.3.0': resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} @@ -3678,11 +3652,11 @@ packages: peerDependencies: vite: ^5.2.0 || ^6 || ^7 - '@tanstack/query-core@5.90.10': - resolution: {integrity: sha512-EhZVFu9rl7GfRNuJLJ3Y7wtbTnENsvzp+YpcAV7kCYiXni1v8qZh++lpw4ch4rrwC0u/EZRnBHIehzCGzwXDSQ==} + '@tanstack/query-core@5.90.11': + resolution: {integrity: sha512-f9z/nXhCgWDF4lHqgIE30jxLe4sYv15QodfdPDKYAk7nAEjNcndy4dHz3ezhdUaR23BpWa4I2EH4/DZ0//Uf8A==} - '@tanstack/react-query@5.90.10': - resolution: {integrity: sha512-BKLss9Y8PQ9IUjPYQiv3/Zmlx92uxffUOX8ZZNoQlCIZBJPT5M+GOMQj7xislvVQ6l1BstBjcX0XB/aHfFYVNw==} + '@tanstack/react-query@5.90.11': + resolution: {integrity: sha512-3uyzz01D1fkTLXuxF3JfoJoHQMU2fxsfJwE+6N5hHy0dVNoZOvwKP8Z2k7k1KDeD54N20apcJnG75TBAStIrBA==} peerDependencies: react: ^18 || ^19 @@ -3899,8 +3873,8 @@ packages: '@types/lodash.debounce@4.0.9': resolution: {integrity: sha512-Ma5JcgTREwpLRwMM+XwBR7DaWe96nC38uCBDFKZWbNKD+osjVzdpnUSwBcqCptrp16sSOLBAUb50Car5I0TCsQ==} - '@types/lodash@4.17.20': - resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==} + '@types/lodash@4.17.21': + resolution: {integrity: sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==} '@types/mdast@3.0.15': resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} @@ -4026,63 +4000,63 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@8.47.0': - resolution: {integrity: sha512-fe0rz9WJQ5t2iaLfdbDc9T80GJy0AeO453q8C3YCilnGozvOyCG5t+EZtg7j7D88+c3FipfP/x+wzGnh1xp8ZA==} + '@typescript-eslint/eslint-plugin@8.48.1': + resolution: {integrity: sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.47.0 + '@typescript-eslint/parser': ^8.48.1 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.47.0': - resolution: {integrity: sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==} + '@typescript-eslint/parser@8.48.1': + resolution: {integrity: sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.47.0': - resolution: {integrity: sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==} + '@typescript-eslint/project-service@8.48.1': + resolution: {integrity: sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.47.0': - resolution: {integrity: sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==} + '@typescript-eslint/scope-manager@8.48.1': + resolution: {integrity: sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.47.0': - resolution: {integrity: sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==} + '@typescript-eslint/tsconfig-utils@8.48.1': + resolution: {integrity: sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.47.0': - resolution: {integrity: sha512-QC9RiCmZ2HmIdCEvhd1aJELBlD93ErziOXXlHEZyuBo3tBiAZieya0HLIxp+DoDWlsQqDawyKuNEhORyku+P8A==} + '@typescript-eslint/type-utils@8.48.1': + resolution: {integrity: sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.47.0': - resolution: {integrity: sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==} + '@typescript-eslint/types@8.48.1': + resolution: {integrity: sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.47.0': - resolution: {integrity: sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==} + '@typescript-eslint/typescript-estree@8.48.1': + resolution: {integrity: sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.47.0': - resolution: {integrity: sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==} + '@typescript-eslint/utils@8.48.1': + resolution: {integrity: sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.47.0': - resolution: {integrity: sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==} + '@typescript-eslint/visitor-keys@8.48.1': + resolution: {integrity: sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typespec/ts-http-runtime@0.3.2': @@ -4435,8 +4409,8 @@ packages: bare-abort-controller: optional: true - bare-fs@4.5.1: - resolution: {integrity: sha512-zGUCsm3yv/ePt2PHNbVxjjn0nNB1MkIaR4wOCxJ2ig5pCf5cCVAYJXVhQg/3OhhJV6DB1ts7Hv0oUaElc2TPQg==} + bare-fs@4.5.2: + resolution: {integrity: sha512-veTnRzkb6aPHOvSKIOy60KzURfBdUflr5VReI+NSaPL6xf+XLdONQgZgpYvUuZLVQ8dCqxpBAudaOM1+KpAUxw==} engines: {bare: '>=1.16.0'} peerDependencies: bare-buffer: '*' @@ -4472,8 +4446,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.8.30: - resolution: {integrity: sha512-aTUKW4ptQhS64+v2d6IkPzymEzzhw+G0bA1g3uBRV3+ntkH+svttKseW5IOR4Ed6NUVKqnY7qT3dKvzQ7io4AA==} + baseline-browser-mapping@2.9.0: + resolution: {integrity: sha512-Mh++g+2LPfzZToywfE1BUzvZbfOY52Nil0rn9H1CPC5DJ7fX+Vir7nToBeoiSbB1zTNeGYbELEvJESujgGrzXw==} hasBin: true basic-ftp@5.0.5: @@ -4507,15 +4481,15 @@ packages: bluebird@3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} - body-parser@2.2.0: - resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} + body-parser@2.2.1: + resolution: {integrity: sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==} engines: {node: '>=18'} boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - bowser@2.12.1: - resolution: {integrity: sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==} + bowser@2.13.1: + resolution: {integrity: sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==} brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} @@ -4527,8 +4501,8 @@ packages: browser-stdout@1.3.1: resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - browserslist@4.28.0: - resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==} + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -4569,6 +4543,10 @@ packages: peerDependencies: esbuild: '>=0.25.0' + busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -4613,8 +4591,8 @@ packages: camelize@1.0.1: resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} - caniuse-lite@1.0.30001756: - resolution: {integrity: sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==} + caniuse-lite@1.0.30001759: + resolution: {integrity: sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -4784,6 +4762,13 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} @@ -4836,9 +4821,6 @@ packages: confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} - confbox@0.2.2: - resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} - consola@3.4.2: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} @@ -5289,8 +5271,8 @@ packages: devtools-protocol@0.0.1367902: resolution: {integrity: sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==} - devtools-protocol@0.0.1521046: - resolution: {integrity: sha512-vhE6eymDQSKWUXwwA37NtTTVEzjtGVfDr3pRbsWEQ5onH/Snp2c+2xZHWJJawG/0hCCJLRGt4xVtEVUVILol4w==} + devtools-protocol@0.0.1534754: + resolution: {integrity: sha512-26T91cV5dbOYnXdJi5qQHoTtUoNEqwkHcAyu/IKtjIAxiEqPMrDiRkDOPWVsGfNZGmlQVHQbZRSjD8sxagWVsQ==} didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} @@ -5495,8 +5477,8 @@ packages: eight-colors@1.3.1: resolution: {integrity: sha512-7nXPYDeKh6DgJDR/mpt2G7N/hCNSGwwoPVmoI3+4TEwOb07VFN1WMPG0DFf6nMEjrkgdj8Og7l7IaEEk3VE6Zg==} - electron-to-chromium@1.5.259: - resolution: {integrity: sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ==} + electron-to-chromium@1.5.264: + resolution: {integrity: sha512-1tEf0nLgltC3iy9wtlYDlQDc5Rg9lEKVjEmIHJ21rI9OcqkvD45K1oyNIRA4rR1z3LgJ7KeGzEBojVcV6m4qjA==} embla-carousel-auto-scroll@8.6.0: resolution: {integrity: sha512-WT9fWhNXFpbQ6kP+aS07oF5IHYLZ1Dx4DkwgCY8Hv2ZyYd2KMCPfMV1q/cA3wFGuLO7GMgKiySLX90/pQkcOdQ==} @@ -5613,8 +5595,8 @@ packages: peerDependencies: esbuild: '>=0.25.0' - esbuild@0.27.0: - resolution: {integrity: sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==} + esbuild@0.27.1: + resolution: {integrity: sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==} engines: {node: '>=18'} hasBin: true @@ -5668,8 +5650,8 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - eslint-plugin-turbo@2.6.1: - resolution: {integrity: sha512-nxwJD6ReZTxEmq/ZNJXI/Mfa3aXctTpQpJrQZESDC1bxjXXcz4i040P7wG6RsRRsQ+9eYB9D+KdCqERpwNZGzw==} + eslint-plugin-turbo@2.6.2: + resolution: {integrity: sha512-FTJOLo8SXLbGgEyFCu0CzrVzEObH2GGJt+cLT6R3oXLK8Bv1i0wOuHYecXjA0RVxZ3t1YUP/9tQNQ3LhTYRd5A==} peerDependencies: eslint: '>6.6.0' turbo: '>2.0.0' @@ -5775,8 +5757,8 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} - execa@9.6.0: - resolution: {integrity: sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==} + execa@9.6.1: + resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==} engines: {node: ^18.19.0 || >=20.5.0} exenv-es6@1.1.1: @@ -5800,13 +5782,10 @@ packages: peerDependencies: express: '>= 4.11' - express@5.1.0: - resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} + express@5.2.1: + resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} - exsolve@1.0.8: - resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} - extend-shallow@2.0.1: resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} engines: {node: '>=0.10.0'} @@ -5914,9 +5893,9 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - finalhandler@2.1.0: - resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} - engines: {node: '>= 0.8'} + finalhandler@2.1.1: + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} find-process@2.0.0: resolution: {integrity: sha512-YUBQnteWGASJoEVVsOXy6XtKAY2O1FCsWnnvQ8y0YwgY1rZiKeVptnFvMu6RSELZAJOGklqseTnUGGs5D0bKmg==} @@ -6145,10 +6124,6 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@15.15.0: - resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} - engines: {node: '>=18'} - globals@16.5.0: resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} engines: {node: '>=18'} @@ -6316,10 +6291,6 @@ packages: htmlparser2@10.0.0: resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} - http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} @@ -6332,8 +6303,8 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} - human-id@4.1.2: - resolution: {integrity: sha512-v/J+4Z/1eIJovEBdlV5TYj1IR+ZiohcYGRY+qN/oC9dAfKzVT023N/Bgw37hrKCoVRBvk3bqyzpr2PP5YeTMSg==} + human-id@4.1.3: + resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} hasBin: true human-signals@2.1.0: @@ -6362,8 +6333,8 @@ packages: i18next-http-backend@3.0.2: resolution: {integrity: sha512-PdlvPnvIp4E1sYi46Ik4tBYh/v/NbYfFFgTjkwFl0is8A18s7/bx9aXqsrOax9WUbeNS6mD2oix7Z0yGGf6m5g==} - i18next@25.6.3: - resolution: {integrity: sha512-AEQvoPDljhp67a1+NsnG/Wb1Nh6YoSvtrmeEd24sfGn3uujCtXCF3cXpr7ulhMywKNFF7p3TX1u2j7y+caLOJg==} + i18next@25.7.1: + resolution: {integrity: sha512-XbTnkh1yCZWSAZGnA9xcQfHcYNgZs2cNxm+c6v1Ma9UAUGCeJPplRe1ILia6xnDvXBjk0uXU+Z8FYWhA19SKFw==} peerDependencies: typescript: ^5 peerDependenciesMeta: @@ -6466,6 +6437,9 @@ packages: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} + is-arrayish@0.3.4: + resolution: {integrity: sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==} + is-async-function@2.1.1: resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} engines: {node: '>= 0.4'} @@ -6745,6 +6719,9 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + jose@6.1.3: + resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==} + joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -6872,8 +6849,8 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - knip@5.70.1: - resolution: {integrity: sha512-tGRjOivkHPV+YoVVDz0oKSlvCAY6d009Mlhufs4Y+7VWl/Ky073+KURcrgMLzJVy4pkpZvoxYu3wmC0gK7XS5g==} + knip@5.71.0: + resolution: {integrity: sha512-hwgdqEJ+7DNJ5jE8BCPu7b57TY7vUwP6MzWYgCgPpg6iPCee/jKPShDNIlFER2koti4oz5xF88VJbKCb4Wl71g==} engines: {node: '>=18.18.0'} hasBin: true peerDependencies: @@ -6883,9 +6860,6 @@ packages: knuth-shuffle-seeded@1.0.6: resolution: {integrity: sha512-9pFH0SplrfyKyojCLxZfMcvkhf5hH0d+UwR9nTVJ/DDQJGuzcXjTwB7TP7sDfehSudlGGaOLblmEWqv04ERVWg==} - kolorist@1.8.0: - resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} - langium@3.3.1: resolution: {integrity: sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==} engines: {node: '>=16.0.0'} @@ -7014,10 +6988,6 @@ packages: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - local-pkg@1.1.2: - resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} - engines: {node: '>=14'} - locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -7134,8 +7104,8 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.2.2: - resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} + lru-cache@11.2.4: + resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} engines: {node: 20 || >=22} lru-cache@5.1.1: @@ -7241,8 +7211,8 @@ packages: mdast-util-to-hast@10.2.0: resolution: {integrity: sha512-JoPBfJ3gBnHZ18icCwHR50orC9kNH81tiR1gs01D8Q5YpV6adHNO9nKNuFBCJQ941/32PT1a63UF/DitmS3amQ==} - mdast-util-to-hast@13.2.0: - resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} + mdast-util-to-hast@13.2.1: + resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} mdast-util-to-markdown@2.1.2: resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} @@ -7284,8 +7254,8 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - mermaid@11.12.1: - resolution: {integrity: sha512-UlIZrRariB11TY1RtTgUWp65tphtBv4CSq7vyS2ZZ2TgoMjs2nloq+wFqxiwcxlhHUvs7DPGgMjs2aeQxz5h9g==} + mermaid@11.12.2: + resolution: {integrity: sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==} micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} @@ -7543,13 +7513,13 @@ packages: react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - next@15.5.6: - resolution: {integrity: sha512-zTxsnI3LQo3c9HSdSf91O1jMNsEzIXDShXd4wVdg9y5shwLqBXi4ZtUUJyB86KGVSJLZx0PFONvO54aheGX8QQ==} + next@15.2.6: + resolution: {integrity: sha512-DIKFctUpZoCq5ok2ztVU+PqhWsbiqM9xNP7rHL2cAp29NQcmDp7Y6JnBBhHRbFt4bCsCZigj6uh+/Gwh2158Wg==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.51.1 + '@playwright/test': ^1.41.2 babel-plugin-react-compiler: '*' react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 @@ -7716,11 +7686,11 @@ packages: oniguruma-parser@0.12.1: resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==} - oniguruma-to-es@4.3.3: - resolution: {integrity: sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==} + oniguruma-to-es@4.3.4: + resolution: {integrity: sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==} - only-allow@1.2.1: - resolution: {integrity: sha512-M7CJbmv7UCopc0neRKdzfoGWaVZC+xC1925GitKH9EAqYFzX9//25Q7oX4+jw0tiCCj+t5l6VZh8UPH23NZkMA==} + only-allow@1.2.2: + resolution: {integrity: sha512-uxyNYDsCh5YIJ780G7hC5OHjVUr9reHsbZNMM80L9tZlTpb3hUzb36KXgW4ZUGtJKQnGA3xegmWg1BxhWV0jJA==} hasBin: true open@10.2.0: @@ -7773,8 +7743,8 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} - oxc-resolver@11.13.2: - resolution: {integrity: sha512-1SXVyYQ9bqMX3uZo8Px81EG7jhZkO9PvvR5X9roY5TLYVm4ZA7pbPDNlYaDBBeF9U+YO3OeMNoHde52hrcCu8w==} + oxc-resolver@11.14.2: + resolution: {integrity: sha512-M5fERQKcrCngMZNnk1gRaBbYcqpqXLgMcoqAo7Wpty+KH0I18i03oiy2peUsGJwFaKAEbmo+CtAyhXh08RZ1RA==} p-filter@2.1.0: resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} @@ -7838,8 +7808,8 @@ packages: package-manager-detector@0.2.11: resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} - package-manager-detector@1.5.0: - resolution: {integrity: sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw==} + package-manager-detector@1.6.0: + resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} pako@0.2.9: resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} @@ -7961,16 +7931,13 @@ packages: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} - pkce-challenge@5.0.0: - resolution: {integrity: sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==} + pkce-challenge@5.0.1: + resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} engines: {node: '>=16.20.0'} pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - pkg-types@2.3.0: - resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} - pngjs@5.0.0: resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} engines: {node: '>=10.13.0'} @@ -8048,15 +8015,15 @@ packages: resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==} engines: {node: '>=12'} - posthog-js@1.297.2: - resolution: {integrity: sha512-pDtCKHpKegV1D5Yk9PBmkFwI9FMnLJm0TsBO5c5/PhPq5Om4y/t+1qqbNcLCdLajkuYl2px9UlRTzycQ6W7Vmw==} + posthog-js@1.301.0: + resolution: {integrity: sha512-HXAXPvE0us6kIPinE/DT3MfuMZNSe0tSRNplXkzGHA03izNFImqh663axROt9+8aaCH1aUCMPDHXrKxvNfVobw==} - posthog-node@5.13.2: - resolution: {integrity: sha512-KfFsiL4v+d723fKYV9vT6lt4GYtryL8FOK7LjlDQ/lJai/EEULkmGvQaNUzBW+4lK9fUaz+AhCyipNDUaXkZqA==} + posthog-node@5.17.0: + resolution: {integrity: sha512-M+ftj0kLJk6wVF1xW5cStSany0LBC6YDVO7RPma2poo+PrpeiTk+ovhqcIqWAySDdTcBHJfBV9aIFYWPl2y6kg==} engines: {node: '>=20'} - preact@10.27.2: - resolution: {integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==} + preact@10.28.0: + resolution: {integrity: sha512-rytDAoiXr3+t6OIP3WGlDd0ouCUG1iCWzkcY3++Nreuoi17y6T5i/zRhe6uYfoVcxq6YU+sBtJouuRDsq8vvqA==} prebuild-install@7.1.3: resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} @@ -8072,8 +8039,8 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - prettier@3.6.2: - resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} + prettier@3.7.4: + resolution: {integrity: sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==} engines: {node: '>=14'} hasBin: true @@ -8161,8 +8128,8 @@ packages: resolution: {integrity: sha512-3HZ2/7hdDKZvZQ7dhhITOUg4/wOrDRjyK2ZBllRB0ZCOi9u0cwq1ACHDjBB+nX+7+kltHjQvBRdeY7+W0T+7Gg==} engines: {node: '>=18'} - puppeteer-core@24.31.0: - resolution: {integrity: sha512-pnAohhSZipWQoFpXuGV7xCZfaGhqcBR9C4pVrU0QSrcMi7tQMH9J9lDBqBvyMAHQqe8HCARuREqFuVKRQOgTvg==} + puppeteer-core@24.32.0: + resolution: {integrity: sha512-MqzLLeJjqjtHK9J44+KE3kjtXXhFpPvg+AvXl/oy/jB8MeeNH66/4MNotOTqGZ6MPaxWi51YJ1ASga6OIff6xw==} engines: {node: '>=18'} q@1.5.1: @@ -8195,8 +8162,8 @@ packages: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} - raw-body@3.0.1: - resolution: {integrity: sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==} + raw-body@3.0.2: + resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} engines: {node: '>= 0.10'} rc@1.2.8: @@ -8214,8 +8181,8 @@ packages: peerDependencies: react: ^18.3.1 - react-hook-form@7.66.1: - resolution: {integrity: sha512-2KnjpgG2Rhbi+CIiIBQQ9Df6sMGH5ExNyFl4Hw9qO7pIqMBR8Bvu9RQyjl3JM4vehzCh9soiNUM/xYMswb2EiA==} + react-hook-form@7.68.0: + resolution: {integrity: sha512-oNN3fjrZ/Xo40SWlHf1yCjlMK417JxoSJVUXQjGdvdRCU07NTFei1i1f8ApUAts+IVh14e4EdakeLEA+BEAs/Q==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 @@ -8276,8 +8243,8 @@ packages: '@types/react': optional: true - react-remove-scroll@2.7.1: - resolution: {integrity: sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==} + react-remove-scroll@2.7.2: + resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} engines: {node: '>=10'} peerDependencies: '@types/react': '*' @@ -8326,8 +8293,8 @@ packages: react: '*' react-dom: '*' - react-virtuoso@4.14.1: - resolution: {integrity: sha512-NRUF1ak8lY+Tvc6WN9cce59gU+lilzVtOozP+pm9J7iHshLGGjsiAB4rB2qlBPHjFbcXOQpT+7womNHGDUql8w==} + react-virtuoso@4.16.1: + resolution: {integrity: sha512-V9ZDw7TFspJb02gNWqHyVZvaMaCFaoL30F/tOVepCI12kdLjA2oxFfWvNC66AVJdOH5cwiq8317p2Q9OpG+TDw==} peerDependencies: react: '>=16 || >=17 || >= 18 || >= 19' react-dom: '>=16 || >=17 || >= 18 || >=19' @@ -8684,8 +8651,8 @@ packages: shallowequal@1.1.0: resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} - sharp@0.34.5: - resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + sharp@0.33.5: + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} shebang-command@2.0.0: @@ -8700,8 +8667,8 @@ packages: resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} engines: {node: '>= 0.4'} - shiki@3.15.0: - resolution: {integrity: sha512-kLdkY6iV3dYbtPwS9KXU7mjfmDm25f5m0IPNFnaXO7TBPcvbUOY72PYXSuSqDzwp+vlH/d7MXpHlKO/x+QoLXw==} + shiki@3.19.0: + resolution: {integrity: sha512-77VJr3OR/VUZzPiStyRhADmO2jApMM0V2b1qf0RpfWya8Zr1PeZev5AEpPGAAKWdiYUtcZGBE4F5QvJml1PvWA==} side-channel-list@1.0.0: resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} @@ -8742,6 +8709,9 @@ packages: resolution: {integrity: sha512-1sbhsxqI+I2tqlmjbz99GXNmZtr6tKIyEgGGnJw/MKGblalqk/XoOYYFJlBzTKZCxx8kLaD3FD5s9BEEjx5Pyg==} engines: {node: '>=10'} + simple-swizzle@0.2.4: + resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==} + sirv@3.0.2: resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} engines: {node: '>=18'} @@ -8847,10 +8817,6 @@ packages: standard-as-callback@2.1.0: resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} - statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - statuses@2.0.2: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} @@ -8875,6 +8841,10 @@ packages: stream-json@1.9.1: resolution: {integrity: sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==} + streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + streamx@2.23.0: resolution: {integrity: sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==} @@ -9268,8 +9238,8 @@ packages: typescript: optional: true - tsx@4.20.6: - resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==} + tsx@4.21.0: + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} engines: {node: '>=18.0.0'} hasBin: true @@ -9280,38 +9250,38 @@ packages: resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - turbo-darwin-64@2.6.1: - resolution: {integrity: sha512-Dm0HwhyZF4J0uLqkhUyCVJvKM9Rw7M03v3J9A7drHDQW0qAbIGBrUijQ8g4Q9Cciw/BXRRd8Uzkc3oue+qn+ZQ==} + turbo-darwin-64@2.6.2: + resolution: {integrity: sha512-nF9d/YAyrNkyXn9lp3ZtgXPb7fZsik3cUNe/sBvUO0G5YezUS/kDYYw77IdjizDzairz8pL2ITCTUreG2d5iZQ==} cpu: [x64] os: [darwin] - turbo-darwin-arm64@2.6.1: - resolution: {integrity: sha512-U0PIPTPyxdLsrC3jN7jaJUwgzX5sVUBsKLO7+6AL+OASaa1NbT1pPdiZoTkblBAALLP76FM0LlnsVQOnmjYhyw==} + turbo-darwin-arm64@2.6.2: + resolution: {integrity: sha512-mmm0jFaVramST26XE1Lk2qjkjvLJHOe9f3TFjqY+aByjMK/ZmKE5WFPuCWo4L3xhwx+16T37rdPP//76loB3oA==} cpu: [arm64] os: [darwin] - turbo-linux-64@2.6.1: - resolution: {integrity: sha512-eM1uLWgzv89bxlK29qwQEr9xYWBhmO/EGiH22UGfq+uXr+QW1OvNKKMogSN65Ry8lElMH4LZh0aX2DEc7eC0Mw==} + turbo-linux-64@2.6.2: + resolution: {integrity: sha512-IUMHjkVRJDUABGpi+iS1Le59aOl5DX88U5UT/mKaE7nNEjG465+a8UtYno56cZnLP+C6BkX4I93LFgYf9syjGQ==} cpu: [x64] os: [linux] - turbo-linux-arm64@2.6.1: - resolution: {integrity: sha512-MFFh7AxAQAycXKuZDrbeutfWM5Ep0CEZ9u7zs4Hn2FvOViTCzIfEhmuJou3/a5+q5VX1zTxQrKGy+4Lf5cdpsA==} + turbo-linux-arm64@2.6.2: + resolution: {integrity: sha512-0qQdZiimMUZj2Gfq87thYu0E02NaNcsB3lcEK/TD70Zzi7AxQoxye664Gis0Uao2j2L9/+05wC2btZ7SoFX3Gw==} cpu: [arm64] os: [linux] - turbo-windows-64@2.6.1: - resolution: {integrity: sha512-buq7/VAN7KOjMYi4tSZT5m+jpqyhbRU2EUTTvp6V0Ii8dAkY2tAAjQN1q5q2ByflYWKecbQNTqxmVploE0LVwQ==} + turbo-windows-64@2.6.2: + resolution: {integrity: sha512-BmMfFmt0VaoZL4NbtDq/dzGfjHsPoGU2+vFiZtkiYsttHY3fd/Dmgnu9PuRyJN1pv2M22q88rXO+dqYRHztLMw==} cpu: [x64] os: [win32] - turbo-windows-arm64@2.6.1: - resolution: {integrity: sha512-7w+AD5vJp3R+FB0YOj1YJcNcOOvBior7bcHTodqp90S3x3bLgpr7tE6xOea1e8JkP7GK6ciKVUpQvV7psiwU5Q==} + turbo-windows-arm64@2.6.2: + resolution: {integrity: sha512-0r4s4M/FgLxfjrdLPdqQUur8vZAtaWEi4jhkQ6wCIN2xzA9aee9IKwM53w7CQcjaLvWhT0AU7LTQHjFaHwxiKw==} cpu: [arm64] os: [win32] - turbo@2.6.1: - resolution: {integrity: sha512-qBwXXuDT3rA53kbNafGbT5r++BrhRgx3sAo0cHoDAeG9g1ItTmUMgltz3Hy7Hazy1ODqNpR+C7QwqL6DYB52yA==} + turbo@2.6.2: + resolution: {integrity: sha512-LiQAFS6iWvnY8ViGtoPgduWBeuGH9B32XR4p8H8jxU5PudwyHiiyf1jQW0fCC8gCCTz9itkIbqZLIyUu5AG33w==} hasBin: true turndown@7.2.2: @@ -9351,8 +9321,8 @@ packages: typed-rest-client@1.8.11: resolution: {integrity: sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==} - typescript-eslint@8.47.0: - resolution: {integrity: sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q==} + typescript-eslint@8.48.1: + resolution: {integrity: sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -9474,8 +9444,8 @@ packages: unzipper@0.10.14: resolution: {integrity: sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==} - update-browserslist-db@1.1.4: - resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} + update-browserslist-db@1.2.1: + resolution: {integrity: sha512-R9NcHbbZ45RoWfTdhn1J9SS7zxNvlddv4YRrHTUaFdtjbmfncfedB45EC9IaqJQ97iAR1GZgOfyRQO+ExIF6EQ==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -9895,8 +9865,8 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - yaml@2.8.1: - resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} + yaml@2.8.2: + resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} engines: {node: '>= 14.6'} hasBin: true @@ -9978,8 +9948,8 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.1.12: - resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==} + zod@4.1.13: + resolution: {integrity: sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==} zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -9992,17 +9962,15 @@ snapshots: '@antfu/install-pkg@1.1.0': dependencies: - package-manager-detector: 1.5.0 + package-manager-detector: 1.6.0 tinyexec: 1.0.2 - '@antfu/utils@9.3.0': {} - '@anthropic-ai/bedrock-sdk@0.10.4': dependencies: '@anthropic-ai/sdk': 0.37.0 '@aws-crypto/sha256-js': 4.0.0 - '@aws-sdk/client-bedrock-runtime': 3.936.0 - '@aws-sdk/credential-providers': 3.936.0 + '@aws-sdk/client-bedrock-runtime': 3.943.0 + '@aws-sdk/credential-providers': 3.943.0 '@smithy/eventstream-serde-node': 2.2.0 '@smithy/fetch-http-handler': 2.5.0 '@smithy/protocol-http': 3.3.0 @@ -10098,27 +10066,27 @@ snapshots: '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-bedrock-runtime@3.936.0': + '@aws-sdk/client-bedrock-runtime@3.943.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.936.0 - '@aws-sdk/credential-provider-node': 3.936.0 + '@aws-sdk/core': 3.943.0 + '@aws-sdk/credential-provider-node': 3.943.0 '@aws-sdk/eventstream-handler-node': 3.936.0 '@aws-sdk/middleware-eventstream': 3.936.0 '@aws-sdk/middleware-host-header': 3.936.0 '@aws-sdk/middleware-logger': 3.936.0 '@aws-sdk/middleware-recursion-detection': 3.936.0 - '@aws-sdk/middleware-user-agent': 3.936.0 + '@aws-sdk/middleware-user-agent': 3.943.0 '@aws-sdk/middleware-websocket': 3.936.0 '@aws-sdk/region-config-resolver': 3.936.0 - '@aws-sdk/token-providers': 3.936.0 + '@aws-sdk/token-providers': 3.943.0 '@aws-sdk/types': 3.936.0 '@aws-sdk/util-endpoints': 3.936.0 '@aws-sdk/util-user-agent-browser': 3.936.0 - '@aws-sdk/util-user-agent-node': 3.936.0 + '@aws-sdk/util-user-agent-node': 3.943.0 '@smithy/config-resolver': 4.4.3 - '@smithy/core': 3.18.5 + '@smithy/core': 3.18.7 '@smithy/eventstream-serde-browser': 4.2.5 '@smithy/eventstream-serde-config-resolver': 4.3.5 '@smithy/eventstream-serde-node': 4.2.5 @@ -10126,21 +10094,21 @@ snapshots: '@smithy/hash-node': 4.2.5 '@smithy/invalid-dependency': 4.2.5 '@smithy/middleware-content-length': 4.2.5 - '@smithy/middleware-endpoint': 4.3.12 - '@smithy/middleware-retry': 4.4.12 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/middleware-retry': 4.4.14 '@smithy/middleware-serde': 4.2.6 '@smithy/middleware-stack': 4.2.5 '@smithy/node-config-provider': 4.3.5 '@smithy/node-http-handler': 4.4.5 '@smithy/protocol-http': 5.3.5 - '@smithy/smithy-client': 4.9.8 + '@smithy/smithy-client': 4.9.10 '@smithy/types': 4.9.0 '@smithy/url-parser': 4.2.5 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.11 - '@smithy/util-defaults-mode-node': 4.2.14 + '@smithy/util-defaults-mode-browser': 4.3.13 + '@smithy/util-defaults-mode-node': 4.2.16 '@smithy/util-endpoints': 3.2.5 '@smithy/util-middleware': 4.2.5 '@smithy/util-retry': 4.2.5 @@ -10150,42 +10118,42 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/client-cognito-identity@3.936.0': + '@aws-sdk/client-cognito-identity@3.943.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.936.0 - '@aws-sdk/credential-provider-node': 3.936.0 + '@aws-sdk/core': 3.943.0 + '@aws-sdk/credential-provider-node': 3.943.0 '@aws-sdk/middleware-host-header': 3.936.0 '@aws-sdk/middleware-logger': 3.936.0 '@aws-sdk/middleware-recursion-detection': 3.936.0 - '@aws-sdk/middleware-user-agent': 3.936.0 + '@aws-sdk/middleware-user-agent': 3.943.0 '@aws-sdk/region-config-resolver': 3.936.0 '@aws-sdk/types': 3.936.0 '@aws-sdk/util-endpoints': 3.936.0 '@aws-sdk/util-user-agent-browser': 3.936.0 - '@aws-sdk/util-user-agent-node': 3.936.0 + '@aws-sdk/util-user-agent-node': 3.943.0 '@smithy/config-resolver': 4.4.3 - '@smithy/core': 3.18.5 + '@smithy/core': 3.18.7 '@smithy/fetch-http-handler': 5.3.6 '@smithy/hash-node': 4.2.5 '@smithy/invalid-dependency': 4.2.5 '@smithy/middleware-content-length': 4.2.5 - '@smithy/middleware-endpoint': 4.3.12 - '@smithy/middleware-retry': 4.4.12 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/middleware-retry': 4.4.14 '@smithy/middleware-serde': 4.2.6 '@smithy/middleware-stack': 4.2.5 '@smithy/node-config-provider': 4.3.5 '@smithy/node-http-handler': 4.4.5 '@smithy/protocol-http': 5.3.5 - '@smithy/smithy-client': 4.9.8 + '@smithy/smithy-client': 4.9.10 '@smithy/types': 4.9.0 '@smithy/url-parser': 4.2.5 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.11 - '@smithy/util-defaults-mode-node': 4.2.14 + '@smithy/util-defaults-mode-browser': 4.3.13 + '@smithy/util-defaults-mode-node': 4.2.16 '@smithy/util-endpoints': 3.2.5 '@smithy/util-middleware': 4.2.5 '@smithy/util-retry': 4.2.5 @@ -10194,41 +10162,41 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sso@3.936.0': + '@aws-sdk/client-sso@3.943.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.936.0 + '@aws-sdk/core': 3.943.0 '@aws-sdk/middleware-host-header': 3.936.0 '@aws-sdk/middleware-logger': 3.936.0 '@aws-sdk/middleware-recursion-detection': 3.936.0 - '@aws-sdk/middleware-user-agent': 3.936.0 + '@aws-sdk/middleware-user-agent': 3.943.0 '@aws-sdk/region-config-resolver': 3.936.0 '@aws-sdk/types': 3.936.0 '@aws-sdk/util-endpoints': 3.936.0 '@aws-sdk/util-user-agent-browser': 3.936.0 - '@aws-sdk/util-user-agent-node': 3.936.0 + '@aws-sdk/util-user-agent-node': 3.943.0 '@smithy/config-resolver': 4.4.3 - '@smithy/core': 3.18.5 + '@smithy/core': 3.18.7 '@smithy/fetch-http-handler': 5.3.6 '@smithy/hash-node': 4.2.5 '@smithy/invalid-dependency': 4.2.5 '@smithy/middleware-content-length': 4.2.5 - '@smithy/middleware-endpoint': 4.3.12 - '@smithy/middleware-retry': 4.4.12 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/middleware-retry': 4.4.14 '@smithy/middleware-serde': 4.2.6 '@smithy/middleware-stack': 4.2.5 '@smithy/node-config-provider': 4.3.5 '@smithy/node-http-handler': 4.4.5 '@smithy/protocol-http': 5.3.5 - '@smithy/smithy-client': 4.9.8 + '@smithy/smithy-client': 4.9.10 '@smithy/types': 4.9.0 '@smithy/url-parser': 4.2.5 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.11 - '@smithy/util-defaults-mode-node': 4.2.14 + '@smithy/util-defaults-mode-browser': 4.3.13 + '@smithy/util-defaults-mode-node': 4.2.16 '@smithy/util-endpoints': 3.2.5 '@smithy/util-middleware': 4.2.5 '@smithy/util-retry': 4.2.5 @@ -10237,25 +10205,25 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/core@3.936.0': + '@aws-sdk/core@3.943.0': dependencies: '@aws-sdk/types': 3.936.0 '@aws-sdk/xml-builder': 3.930.0 - '@smithy/core': 3.18.5 + '@smithy/core': 3.18.7 '@smithy/node-config-provider': 4.3.5 '@smithy/property-provider': 4.2.5 '@smithy/protocol-http': 5.3.5 '@smithy/signature-v4': 5.3.5 - '@smithy/smithy-client': 4.9.8 + '@smithy/smithy-client': 4.9.10 '@smithy/types': 4.9.0 '@smithy/util-base64': 4.3.0 '@smithy/util-middleware': 4.2.5 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-cognito-identity@3.936.0': + '@aws-sdk/credential-provider-cognito-identity@3.943.0': dependencies: - '@aws-sdk/client-cognito-identity': 3.936.0 + '@aws-sdk/client-cognito-identity': 3.943.0 '@aws-sdk/types': 3.936.0 '@smithy/property-provider': 4.2.5 '@smithy/types': 4.9.0 @@ -10263,37 +10231,37 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-env@3.936.0': + '@aws-sdk/credential-provider-env@3.943.0': dependencies: - '@aws-sdk/core': 3.936.0 + '@aws-sdk/core': 3.943.0 '@aws-sdk/types': 3.936.0 '@smithy/property-provider': 4.2.5 '@smithy/types': 4.9.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.936.0': + '@aws-sdk/credential-provider-http@3.943.0': dependencies: - '@aws-sdk/core': 3.936.0 + '@aws-sdk/core': 3.943.0 '@aws-sdk/types': 3.936.0 '@smithy/fetch-http-handler': 5.3.6 '@smithy/node-http-handler': 4.4.5 '@smithy/property-provider': 4.2.5 '@smithy/protocol-http': 5.3.5 - '@smithy/smithy-client': 4.9.8 + '@smithy/smithy-client': 4.9.10 '@smithy/types': 4.9.0 '@smithy/util-stream': 4.5.6 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.936.0': + '@aws-sdk/credential-provider-ini@3.943.0': dependencies: - '@aws-sdk/core': 3.936.0 - '@aws-sdk/credential-provider-env': 3.936.0 - '@aws-sdk/credential-provider-http': 3.936.0 - '@aws-sdk/credential-provider-login': 3.936.0 - '@aws-sdk/credential-provider-process': 3.936.0 - '@aws-sdk/credential-provider-sso': 3.936.0 - '@aws-sdk/credential-provider-web-identity': 3.936.0 - '@aws-sdk/nested-clients': 3.936.0 + '@aws-sdk/core': 3.943.0 + '@aws-sdk/credential-provider-env': 3.943.0 + '@aws-sdk/credential-provider-http': 3.943.0 + '@aws-sdk/credential-provider-login': 3.943.0 + '@aws-sdk/credential-provider-process': 3.943.0 + '@aws-sdk/credential-provider-sso': 3.943.0 + '@aws-sdk/credential-provider-web-identity': 3.943.0 + '@aws-sdk/nested-clients': 3.943.0 '@aws-sdk/types': 3.936.0 '@smithy/credential-provider-imds': 4.2.5 '@smithy/property-provider': 4.2.5 @@ -10303,10 +10271,10 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-login@3.936.0': + '@aws-sdk/credential-provider-login@3.943.0': dependencies: - '@aws-sdk/core': 3.936.0 - '@aws-sdk/nested-clients': 3.936.0 + '@aws-sdk/core': 3.943.0 + '@aws-sdk/nested-clients': 3.943.0 '@aws-sdk/types': 3.936.0 '@smithy/property-provider': 4.2.5 '@smithy/protocol-http': 5.3.5 @@ -10316,14 +10284,14 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-node@3.936.0': + '@aws-sdk/credential-provider-node@3.943.0': dependencies: - '@aws-sdk/credential-provider-env': 3.936.0 - '@aws-sdk/credential-provider-http': 3.936.0 - '@aws-sdk/credential-provider-ini': 3.936.0 - '@aws-sdk/credential-provider-process': 3.936.0 - '@aws-sdk/credential-provider-sso': 3.936.0 - '@aws-sdk/credential-provider-web-identity': 3.936.0 + '@aws-sdk/credential-provider-env': 3.943.0 + '@aws-sdk/credential-provider-http': 3.943.0 + '@aws-sdk/credential-provider-ini': 3.943.0 + '@aws-sdk/credential-provider-process': 3.943.0 + '@aws-sdk/credential-provider-sso': 3.943.0 + '@aws-sdk/credential-provider-web-identity': 3.943.0 '@aws-sdk/types': 3.936.0 '@smithy/credential-provider-imds': 4.2.5 '@smithy/property-provider': 4.2.5 @@ -10333,20 +10301,20 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-process@3.936.0': + '@aws-sdk/credential-provider-process@3.943.0': dependencies: - '@aws-sdk/core': 3.936.0 + '@aws-sdk/core': 3.943.0 '@aws-sdk/types': 3.936.0 '@smithy/property-provider': 4.2.5 '@smithy/shared-ini-file-loader': 4.4.0 '@smithy/types': 4.9.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.936.0': + '@aws-sdk/credential-provider-sso@3.943.0': dependencies: - '@aws-sdk/client-sso': 3.936.0 - '@aws-sdk/core': 3.936.0 - '@aws-sdk/token-providers': 3.936.0 + '@aws-sdk/client-sso': 3.943.0 + '@aws-sdk/core': 3.943.0 + '@aws-sdk/token-providers': 3.943.0 '@aws-sdk/types': 3.936.0 '@smithy/property-provider': 4.2.5 '@smithy/shared-ini-file-loader': 4.4.0 @@ -10355,10 +10323,10 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-web-identity@3.936.0': + '@aws-sdk/credential-provider-web-identity@3.943.0': dependencies: - '@aws-sdk/core': 3.936.0 - '@aws-sdk/nested-clients': 3.936.0 + '@aws-sdk/core': 3.943.0 + '@aws-sdk/nested-clients': 3.943.0 '@aws-sdk/types': 3.936.0 '@smithy/property-provider': 4.2.5 '@smithy/shared-ini-file-loader': 4.4.0 @@ -10367,23 +10335,23 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-providers@3.936.0': - dependencies: - '@aws-sdk/client-cognito-identity': 3.936.0 - '@aws-sdk/core': 3.936.0 - '@aws-sdk/credential-provider-cognito-identity': 3.936.0 - '@aws-sdk/credential-provider-env': 3.936.0 - '@aws-sdk/credential-provider-http': 3.936.0 - '@aws-sdk/credential-provider-ini': 3.936.0 - '@aws-sdk/credential-provider-login': 3.936.0 - '@aws-sdk/credential-provider-node': 3.936.0 - '@aws-sdk/credential-provider-process': 3.936.0 - '@aws-sdk/credential-provider-sso': 3.936.0 - '@aws-sdk/credential-provider-web-identity': 3.936.0 - '@aws-sdk/nested-clients': 3.936.0 + '@aws-sdk/credential-providers@3.943.0': + dependencies: + '@aws-sdk/client-cognito-identity': 3.943.0 + '@aws-sdk/core': 3.943.0 + '@aws-sdk/credential-provider-cognito-identity': 3.943.0 + '@aws-sdk/credential-provider-env': 3.943.0 + '@aws-sdk/credential-provider-http': 3.943.0 + '@aws-sdk/credential-provider-ini': 3.943.0 + '@aws-sdk/credential-provider-login': 3.943.0 + '@aws-sdk/credential-provider-node': 3.943.0 + '@aws-sdk/credential-provider-process': 3.943.0 + '@aws-sdk/credential-provider-sso': 3.943.0 + '@aws-sdk/credential-provider-web-identity': 3.943.0 + '@aws-sdk/nested-clients': 3.943.0 '@aws-sdk/types': 3.936.0 '@smithy/config-resolver': 4.4.3 - '@smithy/core': 3.18.5 + '@smithy/core': 3.18.7 '@smithy/credential-provider-imds': 4.2.5 '@smithy/node-config-provider': 4.3.5 '@smithy/property-provider': 4.2.5 @@ -10422,17 +10390,17 @@ snapshots: '@aws-sdk/middleware-recursion-detection@3.936.0': dependencies: '@aws-sdk/types': 3.936.0 - '@aws/lambda-invoke-store': 0.2.1 + '@aws/lambda-invoke-store': 0.2.2 '@smithy/protocol-http': 5.3.5 '@smithy/types': 4.9.0 tslib: 2.8.1 - '@aws-sdk/middleware-user-agent@3.936.0': + '@aws-sdk/middleware-user-agent@3.943.0': dependencies: - '@aws-sdk/core': 3.936.0 + '@aws-sdk/core': 3.943.0 '@aws-sdk/types': 3.936.0 '@aws-sdk/util-endpoints': 3.936.0 - '@smithy/core': 3.18.5 + '@smithy/core': 3.18.7 '@smithy/protocol-http': 5.3.5 '@smithy/types': 4.9.0 tslib: 2.8.1 @@ -10450,41 +10418,41 @@ snapshots: '@smithy/util-hex-encoding': 4.2.0 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.936.0': + '@aws-sdk/nested-clients@3.943.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.936.0 + '@aws-sdk/core': 3.943.0 '@aws-sdk/middleware-host-header': 3.936.0 '@aws-sdk/middleware-logger': 3.936.0 '@aws-sdk/middleware-recursion-detection': 3.936.0 - '@aws-sdk/middleware-user-agent': 3.936.0 + '@aws-sdk/middleware-user-agent': 3.943.0 '@aws-sdk/region-config-resolver': 3.936.0 '@aws-sdk/types': 3.936.0 '@aws-sdk/util-endpoints': 3.936.0 '@aws-sdk/util-user-agent-browser': 3.936.0 - '@aws-sdk/util-user-agent-node': 3.936.0 + '@aws-sdk/util-user-agent-node': 3.943.0 '@smithy/config-resolver': 4.4.3 - '@smithy/core': 3.18.5 + '@smithy/core': 3.18.7 '@smithy/fetch-http-handler': 5.3.6 '@smithy/hash-node': 4.2.5 '@smithy/invalid-dependency': 4.2.5 '@smithy/middleware-content-length': 4.2.5 - '@smithy/middleware-endpoint': 4.3.12 - '@smithy/middleware-retry': 4.4.12 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/middleware-retry': 4.4.14 '@smithy/middleware-serde': 4.2.6 '@smithy/middleware-stack': 4.2.5 '@smithy/node-config-provider': 4.3.5 '@smithy/node-http-handler': 4.4.5 '@smithy/protocol-http': 5.3.5 - '@smithy/smithy-client': 4.9.8 + '@smithy/smithy-client': 4.9.10 '@smithy/types': 4.9.0 '@smithy/url-parser': 4.2.5 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.11 - '@smithy/util-defaults-mode-node': 4.2.14 + '@smithy/util-defaults-mode-browser': 4.3.13 + '@smithy/util-defaults-mode-node': 4.2.16 '@smithy/util-endpoints': 3.2.5 '@smithy/util-middleware': 4.2.5 '@smithy/util-retry': 4.2.5 @@ -10501,10 +10469,10 @@ snapshots: '@smithy/types': 4.9.0 tslib: 2.8.1 - '@aws-sdk/token-providers@3.936.0': + '@aws-sdk/token-providers@3.943.0': dependencies: - '@aws-sdk/core': 3.936.0 - '@aws-sdk/nested-clients': 3.936.0 + '@aws-sdk/core': 3.943.0 + '@aws-sdk/nested-clients': 3.943.0 '@aws-sdk/types': 3.936.0 '@smithy/property-provider': 4.2.5 '@smithy/shared-ini-file-loader': 4.4.0 @@ -10541,12 +10509,12 @@ snapshots: dependencies: '@aws-sdk/types': 3.936.0 '@smithy/types': 4.9.0 - bowser: 2.12.1 + bowser: 2.13.1 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.936.0': + '@aws-sdk/util-user-agent-node@3.943.0': dependencies: - '@aws-sdk/middleware-user-agent': 3.936.0 + '@aws-sdk/middleware-user-agent': 3.943.0 '@aws-sdk/types': 3.936.0 '@smithy/node-config-provider': 4.3.5 '@smithy/types': 4.9.0 @@ -10562,7 +10530,7 @@ snapshots: fast-xml-parser: 5.2.5 tslib: 2.8.1 - '@aws/lambda-invoke-store@0.2.1': {} + '@aws/lambda-invoke-store@0.2.2': {} '@azure/abort-controller@2.1.2': dependencies: @@ -10687,7 +10655,7 @@ snapshots: dependencies: '@babel/compat-data': 7.28.5 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.0 + browserslist: 4.28.1 lru-cache: 5.1.1 semver: 6.3.1 @@ -10765,9 +10733,9 @@ snapshots: '@braintree/sanitize-url@7.1.1': {} - '@changesets/apply-release-plan@7.0.13': + '@changesets/apply-release-plan@7.0.14': dependencies: - '@changesets/config': 3.1.1 + '@changesets/config': 3.1.2 '@changesets/get-version-range-type': 0.4.0 '@changesets/git': 3.0.4 '@changesets/should-skip-package': 0.1.2 @@ -10794,19 +10762,19 @@ snapshots: dependencies: '@changesets/types': 6.1.0 - '@changesets/cli@2.29.7(@types/node@24.10.1)': + '@changesets/cli@2.29.8(@types/node@24.10.1)': dependencies: - '@changesets/apply-release-plan': 7.0.13 + '@changesets/apply-release-plan': 7.0.14 '@changesets/assemble-release-plan': 6.0.9 '@changesets/changelog-git': 0.2.1 - '@changesets/config': 3.1.1 + '@changesets/config': 3.1.2 '@changesets/errors': 0.2.0 '@changesets/get-dependents-graph': 2.1.3 - '@changesets/get-release-plan': 4.0.13 + '@changesets/get-release-plan': 4.0.14 '@changesets/git': 3.0.4 '@changesets/logger': 0.1.1 '@changesets/pre': 2.0.2 - '@changesets/read': 0.6.5 + '@changesets/read': 0.6.6 '@changesets/should-skip-package': 0.1.2 '@changesets/types': 6.1.0 '@changesets/write': 0.4.0 @@ -10827,7 +10795,7 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@changesets/config@3.1.1': + '@changesets/config@3.1.2': dependencies: '@changesets/errors': 0.2.0 '@changesets/get-dependents-graph': 2.1.3 @@ -10848,12 +10816,12 @@ snapshots: picocolors: 1.1.1 semver: 7.7.3 - '@changesets/get-release-plan@4.0.13': + '@changesets/get-release-plan@4.0.14': dependencies: '@changesets/assemble-release-plan': 6.0.9 - '@changesets/config': 3.1.1 + '@changesets/config': 3.1.2 '@changesets/pre': 2.0.2 - '@changesets/read': 0.6.5 + '@changesets/read': 0.6.6 '@changesets/types': 6.1.0 '@manypkg/get-packages': 1.1.3 @@ -10871,10 +10839,10 @@ snapshots: dependencies: picocolors: 1.1.1 - '@changesets/parse@0.4.1': + '@changesets/parse@0.4.2': dependencies: '@changesets/types': 6.1.0 - js-yaml: 3.14.2 + js-yaml: 4.1.1 '@changesets/pre@2.0.2': dependencies: @@ -10883,11 +10851,11 @@ snapshots: '@manypkg/get-packages': 1.1.3 fs-extra: 7.0.1 - '@changesets/read@0.6.5': + '@changesets/read@0.6.6': dependencies: '@changesets/git': 3.0.4 '@changesets/logger': 0.1.1 - '@changesets/parse': 0.4.1 + '@changesets/parse': 0.4.2 '@changesets/types': 6.1.0 fs-extra: 7.0.1 p-filter: 2.1.0 @@ -10906,7 +10874,7 @@ snapshots: dependencies: '@changesets/types': 6.1.0 fs-extra: 7.0.1 - human-id: 4.1.2 + human-id: 4.1.3 prettier: 2.8.8 '@chevrotain/cst-dts-gen@11.0.3': @@ -10992,7 +10960,7 @@ snapshots: '@esbuild-kit/core-utils@3.3.2': dependencies: - esbuild: 0.27.0 + esbuild: 0.27.1 source-map-support: 0.5.21 '@esbuild-kit/esm-loader@2.6.5': @@ -11000,82 +10968,82 @@ snapshots: '@esbuild-kit/core-utils': 3.3.2 get-tsconfig: 4.13.0 - '@esbuild/aix-ppc64@0.27.0': + '@esbuild/aix-ppc64@0.27.1': optional: true - '@esbuild/android-arm64@0.27.0': + '@esbuild/android-arm64@0.27.1': optional: true - '@esbuild/android-arm@0.27.0': + '@esbuild/android-arm@0.27.1': optional: true - '@esbuild/android-x64@0.27.0': + '@esbuild/android-x64@0.27.1': optional: true - '@esbuild/darwin-arm64@0.27.0': + '@esbuild/darwin-arm64@0.27.1': optional: true - '@esbuild/darwin-x64@0.27.0': + '@esbuild/darwin-x64@0.27.1': optional: true - '@esbuild/freebsd-arm64@0.27.0': + '@esbuild/freebsd-arm64@0.27.1': optional: true - '@esbuild/freebsd-x64@0.27.0': + '@esbuild/freebsd-x64@0.27.1': optional: true - '@esbuild/linux-arm64@0.27.0': + '@esbuild/linux-arm64@0.27.1': optional: true - '@esbuild/linux-arm@0.27.0': + '@esbuild/linux-arm@0.27.1': optional: true - '@esbuild/linux-ia32@0.27.0': + '@esbuild/linux-ia32@0.27.1': optional: true - '@esbuild/linux-loong64@0.27.0': + '@esbuild/linux-loong64@0.27.1': optional: true - '@esbuild/linux-mips64el@0.27.0': + '@esbuild/linux-mips64el@0.27.1': optional: true - '@esbuild/linux-ppc64@0.27.0': + '@esbuild/linux-ppc64@0.27.1': optional: true - '@esbuild/linux-riscv64@0.27.0': + '@esbuild/linux-riscv64@0.27.1': optional: true - '@esbuild/linux-s390x@0.27.0': + '@esbuild/linux-s390x@0.27.1': optional: true - '@esbuild/linux-x64@0.27.0': + '@esbuild/linux-x64@0.27.1': optional: true - '@esbuild/netbsd-arm64@0.27.0': + '@esbuild/netbsd-arm64@0.27.1': optional: true - '@esbuild/netbsd-x64@0.27.0': + '@esbuild/netbsd-x64@0.27.1': optional: true - '@esbuild/openbsd-arm64@0.27.0': + '@esbuild/openbsd-arm64@0.27.1': optional: true - '@esbuild/openbsd-x64@0.27.0': + '@esbuild/openbsd-x64@0.27.1': optional: true - '@esbuild/openharmony-arm64@0.27.0': + '@esbuild/openharmony-arm64@0.27.1': optional: true - '@esbuild/sunos-x64@0.27.0': + '@esbuild/sunos-x64@0.27.1': optional: true - '@esbuild/win32-arm64@0.27.0': + '@esbuild/win32-arm64@0.27.1': optional: true - '@esbuild/win32-ia32@0.27.0': + '@esbuild/win32-ia32@0.27.1': optional: true - '@esbuild/win32-x64@0.27.0': + '@esbuild/win32-x64@0.27.1': optional: true '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(jiti@2.6.1))': @@ -11101,7 +11069,7 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.1': + '@eslint/eslintrc@3.3.3': dependencies: ajv: 6.12.6 debug: 4.4.3(supports-color@8.1.1) @@ -11160,21 +11128,21 @@ snapshots: '@floating-ui/utils@0.2.10': {} - '@google/genai@1.30.0(@modelcontextprotocol/sdk@1.22.0)': + '@google/genai@1.31.0(@modelcontextprotocol/sdk@1.24.2(zod@3.25.76))': dependencies: google-auth-library: 10.5.0 ws: 8.18.3 optionalDependencies: - '@modelcontextprotocol/sdk': 1.22.0 + '@modelcontextprotocol/sdk': 1.24.2(zod@3.25.76) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - '@hookform/resolvers@5.2.2(react-hook-form@7.66.1(react@18.3.1))': + '@hookform/resolvers@5.2.2(react-hook-form@7.68.0(react@18.3.1))': dependencies: '@standard-schema/utils': 0.3.0 - react-hook-form: 7.66.1(react@18.3.1) + react-hook-form: 7.68.0(react@18.3.1) '@humanfs/core@0.19.1': {} @@ -11189,114 +11157,85 @@ snapshots: '@iconify/types@2.0.0': {} - '@iconify/utils@3.0.2': + '@iconify/utils@3.1.0': dependencies: '@antfu/install-pkg': 1.1.0 - '@antfu/utils': 9.3.0 '@iconify/types': 2.0.0 - debug: 4.4.3(supports-color@8.1.1) - globals: 15.15.0 - kolorist: 1.8.0 - local-pkg: 1.1.2 mlly: 1.8.0 - transitivePeerDependencies: - - supports-color - '@img/colour@1.0.0': - optional: true - - '@img/sharp-darwin-arm64@0.34.5': + '@img/sharp-darwin-arm64@0.33.5': optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.2.4 + '@img/sharp-libvips-darwin-arm64': 1.0.4 optional: true - '@img/sharp-darwin-x64@0.34.5': + '@img/sharp-darwin-x64@0.33.5': optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.2.4 - optional: true - - '@img/sharp-libvips-darwin-arm64@1.2.4': + '@img/sharp-libvips-darwin-x64': 1.0.4 optional: true - '@img/sharp-libvips-darwin-x64@1.2.4': + '@img/sharp-libvips-darwin-arm64@1.0.4': optional: true - '@img/sharp-libvips-linux-arm64@1.2.4': + '@img/sharp-libvips-darwin-x64@1.0.4': optional: true - '@img/sharp-libvips-linux-arm@1.2.4': + '@img/sharp-libvips-linux-arm64@1.0.4': optional: true - '@img/sharp-libvips-linux-ppc64@1.2.4': + '@img/sharp-libvips-linux-arm@1.0.5': optional: true - '@img/sharp-libvips-linux-riscv64@1.2.4': + '@img/sharp-libvips-linux-s390x@1.0.4': optional: true - '@img/sharp-libvips-linux-s390x@1.2.4': + '@img/sharp-libvips-linux-x64@1.0.4': optional: true - '@img/sharp-libvips-linux-x64@1.2.4': + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': optional: true - '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + '@img/sharp-libvips-linuxmusl-x64@1.0.4': optional: true - '@img/sharp-libvips-linuxmusl-x64@1.2.4': - optional: true - - '@img/sharp-linux-arm64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.2.4 - optional: true - - '@img/sharp-linux-arm@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.2.4 - optional: true - - '@img/sharp-linux-ppc64@0.34.5': + '@img/sharp-linux-arm64@0.33.5': optionalDependencies: - '@img/sharp-libvips-linux-ppc64': 1.2.4 + '@img/sharp-libvips-linux-arm64': 1.0.4 optional: true - '@img/sharp-linux-riscv64@0.34.5': + '@img/sharp-linux-arm@0.33.5': optionalDependencies: - '@img/sharp-libvips-linux-riscv64': 1.2.4 + '@img/sharp-libvips-linux-arm': 1.0.5 optional: true - '@img/sharp-linux-s390x@0.34.5': + '@img/sharp-linux-s390x@0.33.5': optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.2.4 + '@img/sharp-libvips-linux-s390x': 1.0.4 optional: true - '@img/sharp-linux-x64@0.34.5': + '@img/sharp-linux-x64@0.33.5': optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.2.4 + '@img/sharp-libvips-linux-x64': 1.0.4 optional: true - '@img/sharp-linuxmusl-arm64@0.34.5': + '@img/sharp-linuxmusl-arm64@0.33.5': optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 optional: true - '@img/sharp-linuxmusl-x64@0.34.5': + '@img/sharp-linuxmusl-x64@0.33.5': optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 optional: true - '@img/sharp-wasm32@0.34.5': + '@img/sharp-wasm32@0.33.5': dependencies: '@emnapi/runtime': 1.7.1 optional: true - '@img/sharp-win32-arm64@0.34.5': + '@img/sharp-win32-ia32@0.33.5': optional: true - '@img/sharp-win32-ia32@0.34.5': - optional: true - - '@img/sharp-win32-x64@0.34.5': + '@img/sharp-win32-x64@0.33.5': optional: true '@inquirer/external-editor@1.0.3(@types/node@24.10.1)': @@ -11428,7 +11367,7 @@ snapshots: '@mixmark-io/domino@2.2.0': {} - '@modelcontextprotocol/sdk@1.22.0': + '@modelcontextprotocol/sdk@1.24.2(zod@3.25.76)': dependencies: ajv: 8.17.1 ajv-formats: 3.0.1(ajv@8.17.1) @@ -11437,10 +11376,11 @@ snapshots: cross-spawn: 7.0.6 eventsource: 3.0.7 eventsource-parser: 3.0.6 - express: 5.1.0 - express-rate-limit: 7.5.1(express@5.1.0) - pkce-challenge: 5.0.0 - raw-body: 3.0.1 + express: 5.2.1 + express-rate-limit: 7.5.1(express@5.2.1) + jose: 6.1.3 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 zod: 3.25.76 zod-to-json-schema: 3.25.0(zod@3.25.76) transitivePeerDependencies: @@ -11462,7 +11402,7 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@napi-rs/wasm-runtime@1.0.7': + '@napi-rs/wasm-runtime@1.1.0': dependencies: '@emnapi/core': 1.7.1 '@emnapi/runtime': 1.7.1 @@ -11471,34 +11411,34 @@ snapshots: '@next/env@13.5.11': {} - '@next/env@15.5.6': {} + '@next/env@15.2.6': {} - '@next/eslint-plugin-next@15.5.6': + '@next/eslint-plugin-next@15.5.7': dependencies: fast-glob: 3.3.1 - '@next/swc-darwin-arm64@15.5.6': + '@next/swc-darwin-arm64@15.2.5': optional: true - '@next/swc-darwin-x64@15.5.6': + '@next/swc-darwin-x64@15.2.5': optional: true - '@next/swc-linux-arm64-gnu@15.5.6': + '@next/swc-linux-arm64-gnu@15.2.5': optional: true - '@next/swc-linux-arm64-musl@15.5.6': + '@next/swc-linux-arm64-musl@15.2.5': optional: true - '@next/swc-linux-x64-gnu@15.5.6': + '@next/swc-linux-x64-gnu@15.2.5': optional: true - '@next/swc-linux-x64-musl@15.5.6': + '@next/swc-linux-x64-musl@15.2.5': optional: true - '@next/swc-win32-arm64-msvc@15.5.6': + '@next/swc-win32-arm64-msvc@15.2.5': optional: true - '@next/swc-win32-x64-msvc@15.5.6': + '@next/swc-win32-x64-msvc@15.2.5': optional: true '@noble/ciphers@1.3.0': {} @@ -11593,72 +11533,75 @@ snapshots: '@opentelemetry/api@1.9.0': {} - '@oxc-resolver/binding-android-arm-eabi@11.13.2': + '@oxc-resolver/binding-android-arm-eabi@11.14.2': + optional: true + + '@oxc-resolver/binding-android-arm64@11.14.2': optional: true - '@oxc-resolver/binding-android-arm64@11.13.2': + '@oxc-resolver/binding-darwin-arm64@11.14.2': optional: true - '@oxc-resolver/binding-darwin-arm64@11.13.2': + '@oxc-resolver/binding-darwin-x64@11.14.2': optional: true - '@oxc-resolver/binding-darwin-x64@11.13.2': + '@oxc-resolver/binding-freebsd-x64@11.14.2': optional: true - '@oxc-resolver/binding-freebsd-x64@11.13.2': + '@oxc-resolver/binding-linux-arm-gnueabihf@11.14.2': optional: true - '@oxc-resolver/binding-linux-arm-gnueabihf@11.13.2': + '@oxc-resolver/binding-linux-arm-musleabihf@11.14.2': optional: true - '@oxc-resolver/binding-linux-arm-musleabihf@11.13.2': + '@oxc-resolver/binding-linux-arm64-gnu@11.14.2': optional: true - '@oxc-resolver/binding-linux-arm64-gnu@11.13.2': + '@oxc-resolver/binding-linux-arm64-musl@11.14.2': optional: true - '@oxc-resolver/binding-linux-arm64-musl@11.13.2': + '@oxc-resolver/binding-linux-ppc64-gnu@11.14.2': optional: true - '@oxc-resolver/binding-linux-ppc64-gnu@11.13.2': + '@oxc-resolver/binding-linux-riscv64-gnu@11.14.2': optional: true - '@oxc-resolver/binding-linux-riscv64-gnu@11.13.2': + '@oxc-resolver/binding-linux-riscv64-musl@11.14.2': optional: true - '@oxc-resolver/binding-linux-riscv64-musl@11.13.2': + '@oxc-resolver/binding-linux-s390x-gnu@11.14.2': optional: true - '@oxc-resolver/binding-linux-s390x-gnu@11.13.2': + '@oxc-resolver/binding-linux-x64-gnu@11.14.2': optional: true - '@oxc-resolver/binding-linux-x64-gnu@11.13.2': + '@oxc-resolver/binding-linux-x64-musl@11.14.2': optional: true - '@oxc-resolver/binding-linux-x64-musl@11.13.2': + '@oxc-resolver/binding-openharmony-arm64@11.14.2': optional: true - '@oxc-resolver/binding-wasm32-wasi@11.13.2': + '@oxc-resolver/binding-wasm32-wasi@11.14.2': dependencies: - '@napi-rs/wasm-runtime': 1.0.7 + '@napi-rs/wasm-runtime': 1.1.0 optional: true - '@oxc-resolver/binding-win32-arm64-msvc@11.13.2': + '@oxc-resolver/binding-win32-arm64-msvc@11.14.2': optional: true - '@oxc-resolver/binding-win32-ia32-msvc@11.13.2': + '@oxc-resolver/binding-win32-ia32-msvc@11.14.2': optional: true - '@oxc-resolver/binding-win32-x64-msvc@11.13.2': + '@oxc-resolver/binding-win32-x64-msvc@11.14.2': optional: true '@polka/url@1.0.0-next.29': {} - '@posthog/core@1.5.5': + '@posthog/core@1.7.0': dependencies: cross-spawn: 7.0.6 - '@puppeteer/browsers@2.10.13': + '@puppeteer/browsers@2.11.0': dependencies: debug: 4.4.3(supports-color@8.1.1) extract-zip: 2.0.1 @@ -11689,7 +11632,7 @@ snapshots: - react-native-b4a - supports-color - '@qdrant/js-client-rest@1.16.0(typescript@5.8.3)': + '@qdrant/js-client-rest@1.16.2(typescript@5.8.3)': dependencies: '@qdrant/openapi-typescript-fetch': 1.2.6 typescript: 5.8.3 @@ -11803,7 +11746,7 @@ snapshots: aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.7.1(@types/react@18.3.27)(react@18.3.1) + react-remove-scroll: 2.7.2(@types/react@18.3.27)(react@18.3.1) optionalDependencies: '@types/react': 18.3.27 '@types/react-dom': 18.3.7(@types/react@18.3.27) @@ -11900,7 +11843,7 @@ snapshots: aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.7.1(@types/react@18.3.27)(react@18.3.1) + react-remove-scroll: 2.7.2(@types/react@18.3.27)(react@18.3.1) optionalDependencies: '@types/react': 18.3.27 '@types/react-dom': 18.3.7(@types/react@18.3.27) @@ -11923,7 +11866,7 @@ snapshots: aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.7.1(@types/react@18.3.27)(react@18.3.1) + react-remove-scroll: 2.7.2(@types/react@18.3.27)(react@18.3.1) optionalDependencies: '@types/react': 18.3.27 '@types/react-dom': 18.3.7(@types/react@18.3.27) @@ -12062,7 +12005,7 @@ snapshots: aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.7.1(@types/react@18.3.27)(react@18.3.1) + react-remove-scroll: 2.7.2(@types/react@18.3.27)(react@18.3.1) optionalDependencies: '@types/react': 18.3.27 '@types/react-dom': 18.3.7(@types/react@18.3.27) @@ -12302,33 +12245,33 @@ snapshots: '@sec-ant/readable-stream@0.4.1': {} - '@shikijs/core@3.15.0': + '@shikijs/core@3.19.0': dependencies: - '@shikijs/types': 3.15.0 + '@shikijs/types': 3.19.0 '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 hast-util-to-html: 9.0.5 - '@shikijs/engine-javascript@3.15.0': + '@shikijs/engine-javascript@3.19.0': dependencies: - '@shikijs/types': 3.15.0 + '@shikijs/types': 3.19.0 '@shikijs/vscode-textmate': 10.0.2 - oniguruma-to-es: 4.3.3 + oniguruma-to-es: 4.3.4 - '@shikijs/engine-oniguruma@3.15.0': + '@shikijs/engine-oniguruma@3.19.0': dependencies: - '@shikijs/types': 3.15.0 + '@shikijs/types': 3.19.0 '@shikijs/vscode-textmate': 10.0.2 - '@shikijs/langs@3.15.0': + '@shikijs/langs@3.19.0': dependencies: - '@shikijs/types': 3.15.0 + '@shikijs/types': 3.19.0 - '@shikijs/themes@3.15.0': + '@shikijs/themes@3.19.0': dependencies: - '@shikijs/types': 3.15.0 + '@shikijs/types': 3.19.0 - '@shikijs/types@3.15.0': + '@shikijs/types@3.19.0': dependencies: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 @@ -12363,7 +12306,7 @@ snapshots: '@smithy/util-middleware': 4.2.5 tslib: 2.8.1 - '@smithy/core@3.18.5': + '@smithy/core@3.18.7': dependencies: '@smithy/middleware-serde': 4.2.6 '@smithy/protocol-http': 5.3.5 @@ -12489,9 +12432,9 @@ snapshots: '@smithy/util-middleware': 2.2.0 tslib: 2.8.1 - '@smithy/middleware-endpoint@4.3.12': + '@smithy/middleware-endpoint@4.3.14': dependencies: - '@smithy/core': 3.18.5 + '@smithy/core': 3.18.7 '@smithy/middleware-serde': 4.2.6 '@smithy/node-config-provider': 4.3.5 '@smithy/shared-ini-file-loader': 4.4.0 @@ -12500,12 +12443,12 @@ snapshots: '@smithy/util-middleware': 4.2.5 tslib: 2.8.1 - '@smithy/middleware-retry@4.4.12': + '@smithy/middleware-retry@4.4.14': dependencies: '@smithy/node-config-provider': 4.3.5 '@smithy/protocol-http': 5.3.5 '@smithy/service-error-classification': 4.2.5 - '@smithy/smithy-client': 4.9.8 + '@smithy/smithy-client': 4.9.10 '@smithy/types': 4.9.0 '@smithy/util-middleware': 4.2.5 '@smithy/util-retry': 4.2.5 @@ -12649,10 +12592,10 @@ snapshots: '@smithy/util-stream': 2.2.0 tslib: 2.8.1 - '@smithy/smithy-client@4.9.8': + '@smithy/smithy-client@4.9.10': dependencies: - '@smithy/core': 3.18.5 - '@smithy/middleware-endpoint': 4.3.12 + '@smithy/core': 3.18.7 + '@smithy/middleware-endpoint': 4.3.14 '@smithy/middleware-stack': 4.2.5 '@smithy/protocol-http': 5.3.5 '@smithy/types': 4.9.0 @@ -12722,20 +12665,20 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/util-defaults-mode-browser@4.3.11': + '@smithy/util-defaults-mode-browser@4.3.13': dependencies: '@smithy/property-provider': 4.2.5 - '@smithy/smithy-client': 4.9.8 + '@smithy/smithy-client': 4.9.10 '@smithy/types': 4.9.0 tslib: 2.8.1 - '@smithy/util-defaults-mode-node@4.2.14': + '@smithy/util-defaults-mode-node@4.2.16': dependencies: '@smithy/config-resolver': 4.4.3 '@smithy/credential-provider-imds': 4.2.5 '@smithy/node-config-provider': 4.3.5 '@smithy/property-provider': 4.2.5 - '@smithy/smithy-client': 4.9.8 + '@smithy/smithy-client': 4.9.10 '@smithy/types': 4.9.0 tslib: 2.8.1 @@ -12835,6 +12778,8 @@ snapshots: '@standard-schema/utils@0.3.0': {} + '@swc/counter@0.1.3': {} + '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 @@ -12908,23 +12853,23 @@ snapshots: postcss: 8.5.6 tailwindcss: 4.1.17 - '@tailwindcss/typography@0.5.19(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))': + '@tailwindcss/typography@0.5.19(tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.2))': dependencies: postcss-selector-parser: 6.0.10 - tailwindcss: 3.4.18(tsx@4.20.6)(yaml@2.8.1) + tailwindcss: 3.4.18(tsx@4.21.0)(yaml@2.8.2) - '@tailwindcss/vite@4.1.17(vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1))': + '@tailwindcss/vite@4.1.17(vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@tailwindcss/node': 4.1.17 '@tailwindcss/oxide': 4.1.17 tailwindcss: 4.1.17 - vite: 6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + vite: 6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) - '@tanstack/query-core@5.90.10': {} + '@tanstack/query-core@5.90.11': {} - '@tanstack/react-query@5.90.10(react@18.3.1)': + '@tanstack/react-query@5.90.11(react@18.3.1)': dependencies: - '@tanstack/query-core': 5.90.10 + '@tanstack/query-core': 5.90.11 react: 18.3.1 '@testing-library/dom@10.4.1': @@ -13177,13 +13122,13 @@ snapshots: '@types/lodash-es@4.17.12': dependencies: - '@types/lodash': 4.17.20 + '@types/lodash': 4.17.21 '@types/lodash.debounce@4.0.9': dependencies: - '@types/lodash': 4.17.20 + '@types/lodash': 4.17.21 - '@types/lodash@4.17.20': {} + '@types/lodash@4.17.21': {} '@types/mdast@3.0.15': dependencies: @@ -13303,17 +13248,17 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 24.10.1 + '@types/node': 20.19.25 optional: true - '@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3)': + '@typescript-eslint/eslint-plugin@8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) - '@typescript-eslint/scope-manager': 8.47.0 - '@typescript-eslint/type-utils': 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) - '@typescript-eslint/utils': 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.47.0 + '@typescript-eslint/parser': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.48.1 + '@typescript-eslint/type-utils': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/utils': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.48.1 eslint: 9.39.1(jiti@2.6.1) graphemer: 1.4.0 ignore: 7.0.5 @@ -13323,41 +13268,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3)': + '@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3)': dependencies: - '@typescript-eslint/scope-manager': 8.47.0 - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.47.0 + '@typescript-eslint/scope-manager': 8.48.1 + '@typescript-eslint/types': 8.48.1 + '@typescript-eslint/typescript-estree': 8.48.1(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.48.1 debug: 4.4.3(supports-color@8.1.1) eslint: 9.39.1(jiti@2.6.1) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.47.0(typescript@5.8.3)': + '@typescript-eslint/project-service@8.48.1(typescript@5.8.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.8.3) - '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/tsconfig-utils': 8.48.1(typescript@5.8.3) + '@typescript-eslint/types': 8.48.1 debug: 4.4.3(supports-color@8.1.1) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.47.0': + '@typescript-eslint/scope-manager@8.48.1': dependencies: - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/visitor-keys': 8.47.0 + '@typescript-eslint/types': 8.48.1 + '@typescript-eslint/visitor-keys': 8.48.1 - '@typescript-eslint/tsconfig-utils@8.47.0(typescript@5.8.3)': + '@typescript-eslint/tsconfig-utils@8.48.1(typescript@5.8.3)': dependencies: typescript: 5.8.3 - '@typescript-eslint/type-utils@8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3)': + '@typescript-eslint/type-utils@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3)': dependencies: - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.8.3) - '@typescript-eslint/utils': 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/types': 8.48.1 + '@typescript-eslint/typescript-estree': 8.48.1(typescript@5.8.3) + '@typescript-eslint/utils': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) debug: 4.4.3(supports-color@8.1.1) eslint: 9.39.1(jiti@2.6.1) ts-api-utils: 2.1.0(typescript@5.8.3) @@ -13365,38 +13310,37 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.47.0': {} + '@typescript-eslint/types@8.48.1': {} - '@typescript-eslint/typescript-estree@8.47.0(typescript@5.8.3)': + '@typescript-eslint/typescript-estree@8.48.1(typescript@5.8.3)': dependencies: - '@typescript-eslint/project-service': 8.47.0(typescript@5.8.3) - '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.8.3) - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/visitor-keys': 8.47.0 + '@typescript-eslint/project-service': 8.48.1(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.48.1(typescript@5.8.3) + '@typescript-eslint/types': 8.48.1 + '@typescript-eslint/visitor-keys': 8.48.1 debug: 4.4.3(supports-color@8.1.1) - fast-glob: 3.3.3 - is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.3 + tinyglobby: 0.2.15 ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3)': + '@typescript-eslint/utils@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3)': dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.47.0 - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.48.1 + '@typescript-eslint/types': 8.48.1 + '@typescript-eslint/typescript-estree': 8.48.1(typescript@5.8.3) eslint: 9.39.1(jiti@2.6.1) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.47.0': + '@typescript-eslint/visitor-keys@8.48.1': dependencies: - '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/types': 8.48.1 eslint-visitor-keys: 4.2.1 '@typespec/ts-http-runtime@0.3.2': @@ -13415,7 +13359,7 @@ snapshots: satori: 0.12.2 yoga-wasm-web: 0.3.3 - '@vitejs/plugin-react@4.7.0(vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1))': + '@vitejs/plugin-react@4.7.0(vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) @@ -13423,7 +13367,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + vite: 6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color @@ -13435,21 +13379,21 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1))': + '@vitest/mocker@3.2.4(vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + vite: 6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) - '@vitest/mocker@3.2.4(vite@6.3.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1))': + '@vitest/mocker@3.2.4(vite@6.3.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 6.3.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + vite: 6.3.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) '@vitest/pretty-format@3.2.4': dependencies: @@ -13480,7 +13424,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.15 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) '@vitest/utils@3.2.4': dependencies: @@ -13834,8 +13778,8 @@ snapshots: autoprefixer@10.4.22(postcss@8.5.6): dependencies: - browserslist: 4.28.0 - caniuse-lite: 1.0.30001756 + browserslist: 4.28.1 + caniuse-lite: 1.0.30001759 fraction.js: 5.3.4 normalize-range: 0.1.2 picocolors: 1.1.1 @@ -13869,7 +13813,7 @@ snapshots: bare-events@2.8.2: {} - bare-fs@4.5.1: + bare-fs@4.5.2: dependencies: bare-events: 2.8.2 bare-path: 3.0.0 @@ -13908,7 +13852,7 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.8.30: {} + baseline-browser-mapping@2.9.0: {} basic-ftp@5.0.5: {} @@ -13937,23 +13881,23 @@ snapshots: bluebird@3.7.2: {} - body-parser@2.2.0: + body-parser@2.2.1: dependencies: bytes: 3.1.2 content-type: 1.0.5 debug: 4.4.3(supports-color@8.1.1) http-errors: 2.0.1 - iconv-lite: 0.6.3 + iconv-lite: 0.7.0 on-finished: 2.4.1 qs: 6.14.0 - raw-body: 3.0.1 + raw-body: 3.0.2 type-is: 2.0.1 transitivePeerDependencies: - supports-color boolbase@1.0.0: {} - bowser@2.12.1: {} + bowser@2.13.1: {} brace-expansion@2.0.2: dependencies: @@ -13965,13 +13909,13 @@ snapshots: browser-stdout@1.3.1: {} - browserslist@4.28.0: + browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.8.30 - caniuse-lite: 1.0.30001756 - electron-to-chromium: 1.5.259 + baseline-browser-mapping: 2.9.0 + caniuse-lite: 1.0.30001759 + electron-to-chromium: 1.5.264 node-releases: 2.0.27 - update-browserslist-db: 1.1.4(browserslist@4.28.0) + update-browserslist-db: 1.2.1(browserslist@4.28.1) buffer-crc32@0.2.13: {} @@ -13999,11 +13943,15 @@ snapshots: dependencies: run-applescript: 7.1.0 - bundle-require@5.1.0(esbuild@0.27.0): + bundle-require@5.1.0(esbuild@0.27.1): dependencies: - esbuild: 0.27.0 + esbuild: 0.27.1 load-tsconfig: 0.2.5 + busboy@1.6.0: + dependencies: + streamsearch: 1.1.0 + bytes@3.1.2: {} c8@9.1.0: @@ -14049,7 +13997,7 @@ snapshots: camelize@1.0.1: {} - caniuse-lite@1.0.30001756: {} + caniuse-lite@1.0.30001759: {} ccount@2.0.1: {} @@ -14155,9 +14103,9 @@ snapshots: mitt: 3.0.1 zod: 3.23.8 - chromium-bidi@11.0.0(devtools-protocol@0.0.1521046): + chromium-bidi@11.0.0(devtools-protocol@0.0.1534754): dependencies: - devtools-protocol: 0.0.1521046 + devtools-protocol: 0.0.1534754 mitt: 3.0.1 zod: 3.25.76 @@ -14257,6 +14205,18 @@ snapshots: color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.4 + optional: true + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + optional: true + colorette@2.0.20: {} combined-stream@1.0.8: @@ -14298,8 +14258,6 @@ snapshots: confbox@0.1.8: {} - confbox@0.2.2: {} - consola@3.4.2: {} content-disposition@1.0.1: {} @@ -14741,7 +14699,7 @@ snapshots: devtools-protocol@0.0.1367902: {} - devtools-protocol@0.0.1521046: {} + devtools-protocol@0.0.1534754: {} didyoumean@1.2.2: {} @@ -14818,8 +14776,8 @@ snapshots: dependencies: '@drizzle-team/brocli': 0.10.2 '@esbuild-kit/esm-loader': 2.6.5 - esbuild: 0.27.0 - esbuild-register: 3.6.0(esbuild@0.27.0) + esbuild: 0.27.1 + esbuild-register: 3.6.0(esbuild@0.27.1) transitivePeerDependencies: - supports-color @@ -14861,7 +14819,7 @@ snapshots: eight-colors@1.3.1: {} - electron-to-chromium@1.5.259: {} + electron-to-chromium@1.5.264: {} embla-carousel-auto-scroll@8.6.0(embla-carousel@8.6.0): dependencies: @@ -15039,41 +14997,41 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - esbuild-register@3.6.0(esbuild@0.27.0): + esbuild-register@3.6.0(esbuild@0.27.1): dependencies: debug: 4.4.3(supports-color@8.1.1) - esbuild: 0.27.0 + esbuild: 0.27.1 transitivePeerDependencies: - supports-color - esbuild@0.27.0: + esbuild@0.27.1: optionalDependencies: - '@esbuild/aix-ppc64': 0.27.0 - '@esbuild/android-arm': 0.27.0 - '@esbuild/android-arm64': 0.27.0 - '@esbuild/android-x64': 0.27.0 - '@esbuild/darwin-arm64': 0.27.0 - '@esbuild/darwin-x64': 0.27.0 - '@esbuild/freebsd-arm64': 0.27.0 - '@esbuild/freebsd-x64': 0.27.0 - '@esbuild/linux-arm': 0.27.0 - '@esbuild/linux-arm64': 0.27.0 - '@esbuild/linux-ia32': 0.27.0 - '@esbuild/linux-loong64': 0.27.0 - '@esbuild/linux-mips64el': 0.27.0 - '@esbuild/linux-ppc64': 0.27.0 - '@esbuild/linux-riscv64': 0.27.0 - '@esbuild/linux-s390x': 0.27.0 - '@esbuild/linux-x64': 0.27.0 - '@esbuild/netbsd-arm64': 0.27.0 - '@esbuild/netbsd-x64': 0.27.0 - '@esbuild/openbsd-arm64': 0.27.0 - '@esbuild/openbsd-x64': 0.27.0 - '@esbuild/openharmony-arm64': 0.27.0 - '@esbuild/sunos-x64': 0.27.0 - '@esbuild/win32-arm64': 0.27.0 - '@esbuild/win32-ia32': 0.27.0 - '@esbuild/win32-x64': 0.27.0 + '@esbuild/aix-ppc64': 0.27.1 + '@esbuild/android-arm': 0.27.1 + '@esbuild/android-arm64': 0.27.1 + '@esbuild/android-x64': 0.27.1 + '@esbuild/darwin-arm64': 0.27.1 + '@esbuild/darwin-x64': 0.27.1 + '@esbuild/freebsd-arm64': 0.27.1 + '@esbuild/freebsd-x64': 0.27.1 + '@esbuild/linux-arm': 0.27.1 + '@esbuild/linux-arm64': 0.27.1 + '@esbuild/linux-ia32': 0.27.1 + '@esbuild/linux-loong64': 0.27.1 + '@esbuild/linux-mips64el': 0.27.1 + '@esbuild/linux-ppc64': 0.27.1 + '@esbuild/linux-riscv64': 0.27.1 + '@esbuild/linux-s390x': 0.27.1 + '@esbuild/linux-x64': 0.27.1 + '@esbuild/netbsd-arm64': 0.27.1 + '@esbuild/netbsd-x64': 0.27.1 + '@esbuild/openbsd-arm64': 0.27.1 + '@esbuild/openbsd-x64': 0.27.1 + '@esbuild/openharmony-arm64': 0.27.1 + '@esbuild/sunos-x64': 0.27.1 + '@esbuild/win32-arm64': 0.27.1 + '@esbuild/win32-ia32': 0.27.1 + '@esbuild/win32-x64': 0.27.1 escalade@3.2.0: {} @@ -15127,11 +15085,11 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-turbo@2.6.1(eslint@9.39.1(jiti@2.6.1))(turbo@2.6.1): + eslint-plugin-turbo@2.6.2(eslint@9.39.1(jiti@2.6.1))(turbo@2.6.2): dependencies: dotenv: 16.0.3 eslint: 9.39.1(jiti@2.6.1) - turbo: 2.6.1 + turbo: 2.6.2 eslint-scope@8.4.0: dependencies: @@ -15149,7 +15107,7 @@ snapshots: '@eslint/config-array': 0.21.1 '@eslint/config-helpers': 0.4.2 '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.1 + '@eslint/eslintrc': 3.3.3 '@eslint/js': 9.39.1 '@eslint/plugin-kit': 0.4.1 '@humanfs/node': 0.16.7 @@ -15282,7 +15240,7 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 - execa@9.6.0: + execa@9.6.1: dependencies: '@sindresorhus/merge-streams': 4.0.0 cross-spawn: 7.0.6 @@ -15312,23 +15270,24 @@ snapshots: jest-message-util: 29.7.0 jest-util: 29.7.0 - express-rate-limit@7.5.1(express@5.1.0): + express-rate-limit@7.5.1(express@5.2.1): dependencies: - express: 5.1.0 + express: 5.2.1 - express@5.1.0: + express@5.2.1: dependencies: accepts: 2.0.0 - body-parser: 2.2.0 + body-parser: 2.2.1 content-disposition: 1.0.1 content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.2.2 debug: 4.4.3(supports-color@8.1.1) + depd: 2.0.0 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 - finalhandler: 2.1.0 + finalhandler: 2.1.1 fresh: 2.0.0 http-errors: 2.0.1 merge-descriptors: 2.0.0 @@ -15348,8 +15307,6 @@ snapshots: transitivePeerDependencies: - supports-color - exsolve@1.0.8: {} - extend-shallow@2.0.1: dependencies: is-extendable: 0.1.1 @@ -15454,7 +15411,7 @@ snapshots: dependencies: to-regex-range: 5.0.1 - finalhandler@2.1.0: + finalhandler@2.1.1: dependencies: debug: 4.4.3(supports-color@8.1.1) encodeurl: 2.0.0 @@ -15708,8 +15665,6 @@ snapshots: globals@14.0.0: {} - globals@15.15.0: {} - globals@16.5.0: {} globalthis@1.0.4: @@ -15869,7 +15824,7 @@ snapshots: hast-util-from-parse5: 8.0.3 hast-util-to-parse5: 8.0.0 html-void-elements: 3.0.0 - mdast-util-to-hast: 13.2.0 + mdast-util-to-hast: 13.2.1 parse5: 7.3.0 unist-util-position: 5.0.0 unist-util-visit: 5.0.0 @@ -15885,7 +15840,7 @@ snapshots: comma-separated-tokens: 2.0.3 hast-util-whitespace: 3.0.0 html-void-elements: 3.0.0 - mdast-util-to-hast: 13.2.0 + mdast-util-to-hast: 13.2.1 property-information: 7.1.0 space-separated-tokens: 2.0.2 stringify-entities: 4.0.4 @@ -15973,14 +15928,6 @@ snapshots: domutils: 3.2.2 entities: 6.0.1 - http-errors@2.0.0: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -16003,7 +15950,7 @@ snapshots: transitivePeerDependencies: - supports-color - human-id@4.1.2: {} + human-id@4.1.3: {} human-signals@2.1.0: {} @@ -16025,7 +15972,7 @@ snapshots: transitivePeerDependencies: - encoding - i18next@25.6.3(typescript@5.8.3): + i18next@25.7.1(typescript@5.8.3): dependencies: '@babel/runtime': 7.28.4 optionalDependencies: @@ -16123,6 +16070,9 @@ snapshots: call-bound: 1.0.4 get-intrinsic: 1.3.0 + is-arrayish@0.3.4: + optional: true + is-async-function@2.1.1: dependencies: async-function: 1.0.0 @@ -16378,6 +16328,8 @@ snapshots: jiti@2.6.1: {} + jose@6.1.3: {} + joycon@3.1.1: {} js-cookie@2.2.1: {} @@ -16531,7 +16483,7 @@ snapshots: kind-of@6.0.3: {} - knip@5.70.1(@types/node@24.10.1)(typescript@5.8.3): + knip@5.71.0(@types/node@24.10.1)(typescript@5.8.3): dependencies: '@nodelib/fs.walk': 1.2.8 '@types/node': 24.10.1 @@ -16540,20 +16492,18 @@ snapshots: jiti: 2.6.1 js-yaml: 4.1.1 minimist: 1.2.8 - oxc-resolver: 11.13.2 + oxc-resolver: 11.14.2 picocolors: 1.1.1 picomatch: 4.0.3 smol-toml: 1.5.2 strip-json-comments: 5.0.3 typescript: 5.8.3 - zod: 4.1.12 + zod: 4.1.13 knuth-shuffle-seeded@1.0.6: dependencies: seed-random: 2.2.0 - kolorist@1.8.0: {} - langium@3.3.1: dependencies: chevrotain: 11.0.3 @@ -16655,7 +16605,7 @@ snapshots: nano-spawn: 2.0.0 pidtree: 0.6.0 string-argv: 0.3.2 - yaml: 2.8.1 + yaml: 2.8.2 listenercount@1.0.1: {} @@ -16670,12 +16620,6 @@ snapshots: load-tsconfig@0.2.5: {} - local-pkg@1.1.2: - dependencies: - mlly: 1.8.0 - pkg-types: 2.3.0 - quansync: 0.2.11 - locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -16774,7 +16718,7 @@ snapshots: lru-cache@10.4.3: {} - lru-cache@11.2.2: {} + lru-cache@11.2.4: {} lru-cache@5.1.1: dependencies: @@ -16994,7 +16938,7 @@ snapshots: unist-util-position: 3.1.0 unist-util-visit: 2.0.3 - mdast-util-to-hast@13.2.0: + mdast-util-to-hast@13.2.1: dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 @@ -17042,10 +16986,10 @@ snapshots: merge2@1.4.1: {} - mermaid@11.12.1: + mermaid@11.12.2: dependencies: '@braintree/sanitize-url': 7.1.1 - '@iconify/utils': 3.0.2 + '@iconify/utils': 3.1.0 '@mermaid-js/parser': 0.6.3 '@types/d3': 7.4.3 cytoscape: 3.33.1 @@ -17064,8 +17008,6 @@ snapshots: stylis: 4.3.6 ts-dedent: 2.2.0 uuid: 11.1.0 - transitivePeerDependencies: - - supports-color micromark-core-commonmark@2.0.3: dependencies: @@ -17421,39 +17363,41 @@ snapshots: netmask@2.0.2: {} - next-sitemap@4.2.3(next@15.5.6(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)): + next-sitemap@4.2.3(next@15.2.6(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)): dependencies: '@corex/deepmerge': 4.0.43 '@next/env': 13.5.11 fast-glob: 3.3.3 minimist: 1.2.8 - next: 15.5.6(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 15.2.6(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-themes@0.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@15.5.6(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@15.2.6(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@next/env': 15.5.6 + '@next/env': 15.2.6 + '@swc/counter': 0.1.3 '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001756 + busboy: 1.6.0 + caniuse-lite: 1.0.30001759 postcss: 8.4.31 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) styled-jsx: 5.1.6(react@18.3.1) optionalDependencies: - '@next/swc-darwin-arm64': 15.5.6 - '@next/swc-darwin-x64': 15.5.6 - '@next/swc-linux-arm64-gnu': 15.5.6 - '@next/swc-linux-arm64-musl': 15.5.6 - '@next/swc-linux-x64-gnu': 15.5.6 - '@next/swc-linux-x64-musl': 15.5.6 - '@next/swc-win32-arm64-msvc': 15.5.6 - '@next/swc-win32-x64-msvc': 15.5.6 + '@next/swc-darwin-arm64': 15.2.5 + '@next/swc-darwin-x64': 15.2.5 + '@next/swc-linux-arm64-gnu': 15.2.5 + '@next/swc-linux-arm64-musl': 15.2.5 + '@next/swc-linux-x64-gnu': 15.2.5 + '@next/swc-linux-x64-musl': 15.2.5 + '@next/swc-win32-arm64-msvc': 15.2.5 + '@next/swc-win32-x64-msvc': 15.2.5 '@opentelemetry/api': 1.9.0 - sharp: 0.34.5 + sharp: 0.33.5 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -17622,13 +17566,13 @@ snapshots: oniguruma-parser@0.12.1: {} - oniguruma-to-es@4.3.3: + oniguruma-to-es@4.3.4: dependencies: oniguruma-parser: 0.12.1 regex: 6.0.1 regex-recursion: 6.0.2 - only-allow@1.2.1: + only-allow@1.2.2: dependencies: which-pm-runs: 1.1.0 @@ -17703,27 +17647,28 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 - oxc-resolver@11.13.2: + oxc-resolver@11.14.2: optionalDependencies: - '@oxc-resolver/binding-android-arm-eabi': 11.13.2 - '@oxc-resolver/binding-android-arm64': 11.13.2 - '@oxc-resolver/binding-darwin-arm64': 11.13.2 - '@oxc-resolver/binding-darwin-x64': 11.13.2 - '@oxc-resolver/binding-freebsd-x64': 11.13.2 - '@oxc-resolver/binding-linux-arm-gnueabihf': 11.13.2 - '@oxc-resolver/binding-linux-arm-musleabihf': 11.13.2 - '@oxc-resolver/binding-linux-arm64-gnu': 11.13.2 - '@oxc-resolver/binding-linux-arm64-musl': 11.13.2 - '@oxc-resolver/binding-linux-ppc64-gnu': 11.13.2 - '@oxc-resolver/binding-linux-riscv64-gnu': 11.13.2 - '@oxc-resolver/binding-linux-riscv64-musl': 11.13.2 - '@oxc-resolver/binding-linux-s390x-gnu': 11.13.2 - '@oxc-resolver/binding-linux-x64-gnu': 11.13.2 - '@oxc-resolver/binding-linux-x64-musl': 11.13.2 - '@oxc-resolver/binding-wasm32-wasi': 11.13.2 - '@oxc-resolver/binding-win32-arm64-msvc': 11.13.2 - '@oxc-resolver/binding-win32-ia32-msvc': 11.13.2 - '@oxc-resolver/binding-win32-x64-msvc': 11.13.2 + '@oxc-resolver/binding-android-arm-eabi': 11.14.2 + '@oxc-resolver/binding-android-arm64': 11.14.2 + '@oxc-resolver/binding-darwin-arm64': 11.14.2 + '@oxc-resolver/binding-darwin-x64': 11.14.2 + '@oxc-resolver/binding-freebsd-x64': 11.14.2 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.14.2 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.14.2 + '@oxc-resolver/binding-linux-arm64-gnu': 11.14.2 + '@oxc-resolver/binding-linux-arm64-musl': 11.14.2 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.14.2 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.14.2 + '@oxc-resolver/binding-linux-riscv64-musl': 11.14.2 + '@oxc-resolver/binding-linux-s390x-gnu': 11.14.2 + '@oxc-resolver/binding-linux-x64-gnu': 11.14.2 + '@oxc-resolver/binding-linux-x64-musl': 11.14.2 + '@oxc-resolver/binding-openharmony-arm64': 11.14.2 + '@oxc-resolver/binding-wasm32-wasi': 11.14.2 + '@oxc-resolver/binding-win32-arm64-msvc': 11.14.2 + '@oxc-resolver/binding-win32-ia32-msvc': 11.14.2 + '@oxc-resolver/binding-win32-x64-msvc': 11.14.2 p-filter@2.1.0: dependencies: @@ -17790,7 +17735,7 @@ snapshots: dependencies: quansync: 0.2.11 - package-manager-detector@1.5.0: {} + package-manager-detector@1.6.0: {} pako@0.2.9: {} @@ -17861,7 +17806,7 @@ snapshots: path-scurry@2.0.1: dependencies: - lru-cache: 11.2.2 + lru-cache: 11.2.4 minipass: 7.1.2 path-to-regexp@8.3.0: {} @@ -17896,7 +17841,7 @@ snapshots: pirates@4.0.7: {} - pkce-challenge@5.0.0: {} + pkce-challenge@5.0.1: {} pkg-types@1.3.1: dependencies: @@ -17904,12 +17849,6 @@ snapshots: mlly: 1.8.0 pathe: 2.0.3 - pkg-types@2.3.0: - dependencies: - confbox: 0.2.2 - exsolve: 1.0.8 - pathe: 2.0.3 - pngjs@5.0.0: {} points-on-curve@0.2.0: {} @@ -17933,23 +17872,23 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.5.6 - postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.6)(yaml@2.8.1): + postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2): dependencies: lilconfig: 3.1.3 optionalDependencies: jiti: 1.21.7 postcss: 8.5.6 - tsx: 4.20.6 - yaml: 2.8.1 + tsx: 4.21.0 + yaml: 2.8.2 - postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.6)(yaml@2.8.1): + postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2): dependencies: lilconfig: 3.1.3 optionalDependencies: jiti: 2.6.1 postcss: 8.5.6 - tsx: 4.20.6 - yaml: 2.8.1 + tsx: 4.21.0 + yaml: 2.8.2 postcss-nested@6.2.0(postcss@8.5.6): dependencies: @@ -17988,19 +17927,19 @@ snapshots: postgres@3.4.7: {} - posthog-js@1.297.2: + posthog-js@1.301.0: dependencies: - '@posthog/core': 1.5.5 + '@posthog/core': 1.7.0 core-js: 3.47.0 fflate: 0.4.8 - preact: 10.27.2 + preact: 10.28.0 web-vitals: 4.2.4 - posthog-node@5.13.2: + posthog-node@5.17.0: dependencies: - '@posthog/core': 1.5.5 + '@posthog/core': 1.7.0 - preact@10.27.2: {} + preact@10.28.0: {} prebuild-install@7.1.3: dependencies: @@ -18026,7 +17965,7 @@ snapshots: prettier@2.8.8: {} - prettier@3.6.2: {} + prettier@3.7.4: {} pretty-bytes@7.1.0: {} @@ -18114,10 +18053,10 @@ snapshots: puppeteer-chromium-resolver@24.0.3: dependencies: - '@puppeteer/browsers': 2.10.13 + '@puppeteer/browsers': 2.11.0 cli-progress: 3.12.0 eight-colors: 1.3.1 - puppeteer-core: 24.31.0 + puppeteer-core: 24.32.0 transitivePeerDependencies: - bare-abort-controller - bare-buffer @@ -18142,12 +18081,12 @@ snapshots: - supports-color - utf-8-validate - puppeteer-core@24.31.0: + puppeteer-core@24.32.0: dependencies: - '@puppeteer/browsers': 2.10.13 - chromium-bidi: 11.0.0(devtools-protocol@0.0.1521046) + '@puppeteer/browsers': 2.11.0 + chromium-bidi: 11.0.0(devtools-protocol@0.0.1534754) debug: 4.4.3(supports-color@8.1.1) - devtools-protocol: 0.0.1521046 + devtools-protocol: 0.0.1534754 typed-query-selector: 2.12.0 webdriver-bidi-protocol: 0.3.9 ws: 8.18.3 @@ -18181,10 +18120,10 @@ snapshots: range-parser@1.2.1: {} - raw-body@3.0.1: + raw-body@3.0.2: dependencies: bytes: 3.1.2 - http-errors: 2.0.0 + http-errors: 2.0.1 iconv-lite: 0.7.0 unpipe: 1.0.0 @@ -18207,15 +18146,15 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 - react-hook-form@7.66.1(react@18.3.1): + react-hook-form@7.68.0(react@18.3.1): dependencies: react: 18.3.1 - react-i18next@15.7.4(i18next@25.6.3(typescript@5.8.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3): + react-i18next@15.7.4(i18next@25.7.1(typescript@5.8.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3): dependencies: '@babel/runtime': 7.28.4 html-parse-stringify: 3.0.1 - i18next: 25.6.3(typescript@5.8.3) + i18next: 25.7.1(typescript@5.8.3) react: 18.3.1 optionalDependencies: react-dom: 18.3.1(react@18.3.1) @@ -18239,7 +18178,7 @@ snapshots: devlop: 1.1.0 hast-util-to-jsx-runtime: 2.3.6 html-url-attributes: 3.0.1 - mdast-util-to-hast: 13.2.0 + mdast-util-to-hast: 13.2.1 react: 18.3.1 remark-parse: 11.0.0 remark-rehype: 11.1.2 @@ -18269,7 +18208,7 @@ snapshots: optionalDependencies: '@types/react': 18.3.27 - react-remove-scroll@2.7.1(@types/react@18.3.27)(react@18.3.1): + react-remove-scroll@2.7.2(@types/react@18.3.27)(react@18.3.1): dependencies: react: 18.3.1 react-remove-scroll-bar: 2.3.8(@types/react@18.3.27)(react@18.3.1) @@ -18338,7 +18277,7 @@ snapshots: ts-easing: 0.2.0 tslib: 2.8.1 - react-virtuoso@4.14.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + react-virtuoso@4.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -18544,7 +18483,7 @@ snapshots: dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 - mdast-util-to-hast: 13.2.0 + mdast-util-to-hast: 13.2.1 unified: 11.0.5 vfile: 6.0.3 @@ -18827,36 +18766,31 @@ snapshots: shallowequal@1.1.0: {} - sharp@0.34.5: + sharp@0.33.5: dependencies: - '@img/colour': 1.0.0 + color: 4.2.3 detect-libc: 2.1.2 semver: 7.7.3 optionalDependencies: - '@img/sharp-darwin-arm64': 0.34.5 - '@img/sharp-darwin-x64': 0.34.5 - '@img/sharp-libvips-darwin-arm64': 1.2.4 - '@img/sharp-libvips-darwin-x64': 1.2.4 - '@img/sharp-libvips-linux-arm': 1.2.4 - '@img/sharp-libvips-linux-arm64': 1.2.4 - '@img/sharp-libvips-linux-ppc64': 1.2.4 - '@img/sharp-libvips-linux-riscv64': 1.2.4 - '@img/sharp-libvips-linux-s390x': 1.2.4 - '@img/sharp-libvips-linux-x64': 1.2.4 - '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 - '@img/sharp-libvips-linuxmusl-x64': 1.2.4 - '@img/sharp-linux-arm': 0.34.5 - '@img/sharp-linux-arm64': 0.34.5 - '@img/sharp-linux-ppc64': 0.34.5 - '@img/sharp-linux-riscv64': 0.34.5 - '@img/sharp-linux-s390x': 0.34.5 - '@img/sharp-linux-x64': 0.34.5 - '@img/sharp-linuxmusl-arm64': 0.34.5 - '@img/sharp-linuxmusl-x64': 0.34.5 - '@img/sharp-wasm32': 0.34.5 - '@img/sharp-win32-arm64': 0.34.5 - '@img/sharp-win32-ia32': 0.34.5 - '@img/sharp-win32-x64': 0.34.5 + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-libvips-darwin-arm64': 1.0.4 + '@img/sharp-libvips-darwin-x64': 1.0.4 + '@img/sharp-libvips-linux-arm': 1.0.5 + '@img/sharp-libvips-linux-arm64': 1.0.4 + '@img/sharp-libvips-linux-s390x': 1.0.4 + '@img/sharp-libvips-linux-x64': 1.0.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-s390x': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-linuxmusl-arm64': 0.33.5 + '@img/sharp-linuxmusl-x64': 0.33.5 + '@img/sharp-wasm32': 0.33.5 + '@img/sharp-win32-ia32': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 optional: true shebang-command@2.0.0: @@ -18867,14 +18801,14 @@ snapshots: shell-quote@1.8.3: {} - shiki@3.15.0: + shiki@3.19.0: dependencies: - '@shikijs/core': 3.15.0 - '@shikijs/engine-javascript': 3.15.0 - '@shikijs/engine-oniguruma': 3.15.0 - '@shikijs/langs': 3.15.0 - '@shikijs/themes': 3.15.0 - '@shikijs/types': 3.15.0 + '@shikijs/core': 3.19.0 + '@shikijs/engine-javascript': 3.19.0 + '@shikijs/engine-oniguruma': 3.19.0 + '@shikijs/langs': 3.19.0 + '@shikijs/themes': 3.19.0 + '@shikijs/types': 3.19.0 '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 @@ -18932,6 +18866,11 @@ snapshots: simple-invariant@2.0.1: {} + simple-swizzle@0.2.4: + dependencies: + is-arrayish: 0.3.4 + optional: true + sirv@3.0.2: dependencies: '@polka/url': 1.0.0-next.29 @@ -19042,8 +18981,6 @@ snapshots: standard-as-callback@2.1.0: {} - statuses@2.0.1: {} - statuses@2.0.2: {} std-env@3.10.0: {} @@ -19065,6 +19002,8 @@ snapshots: dependencies: stream-chain: 2.2.5 + streamsearch@1.1.0: {} + streamx@2.23.0: dependencies: events-universal: 1.0.1 @@ -19282,15 +19221,15 @@ snapshots: tailwind-merge@3.4.0: {} - tailwindcss-animate@1.0.7(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1)): + tailwindcss-animate@1.0.7(tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.2)): dependencies: - tailwindcss: 3.4.18(tsx@4.20.6)(yaml@2.8.1) + tailwindcss: 3.4.18(tsx@4.21.0)(yaml@2.8.2) tailwindcss-animate@1.0.7(tailwindcss@4.1.17): dependencies: tailwindcss: 4.1.17 - tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1): + tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.2): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -19309,7 +19248,7 @@ snapshots: postcss: 8.5.6 postcss-import: 15.1.0(postcss@8.5.6) postcss-js: 4.1.0(postcss@8.5.6) - postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.6)(yaml@2.8.1) + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2) postcss-nested: 6.2.0(postcss@8.5.6) postcss-selector-parser: 6.1.2 resolve: 1.22.11 @@ -19327,7 +19266,7 @@ snapshots: pump: 3.0.3 tar-stream: 3.1.7 optionalDependencies: - bare-fs: 4.5.1 + bare-fs: 4.5.2 bare-path: 3.0.0 transitivePeerDependencies: - bare-abort-controller @@ -19469,18 +19408,18 @@ snapshots: tslib@2.8.1: {} - tsup@8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.6)(typescript@5.8.3)(yaml@2.8.1): + tsup@8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.2): dependencies: - bundle-require: 5.1.0(esbuild@0.27.0) + bundle-require: 5.1.0(esbuild@0.27.1) cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.2 debug: 4.4.3(supports-color@8.1.1) - esbuild: 0.27.0 + esbuild: 0.27.1 fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.6)(yaml@2.8.1) + postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2) resolve-from: 5.0.0 rollup: 4.53.3 source-map: 0.7.6 @@ -19497,9 +19436,9 @@ snapshots: - tsx - yaml - tsx@4.20.6: + tsx@4.21.0: dependencies: - esbuild: 0.27.0 + esbuild: 0.27.1 get-tsconfig: 4.13.0 optionalDependencies: fsevents: 2.3.3 @@ -19511,32 +19450,32 @@ snapshots: tunnel@0.0.6: {} - turbo-darwin-64@2.6.1: + turbo-darwin-64@2.6.2: optional: true - turbo-darwin-arm64@2.6.1: + turbo-darwin-arm64@2.6.2: optional: true - turbo-linux-64@2.6.1: + turbo-linux-64@2.6.2: optional: true - turbo-linux-arm64@2.6.1: + turbo-linux-arm64@2.6.2: optional: true - turbo-windows-64@2.6.1: + turbo-windows-64@2.6.2: optional: true - turbo-windows-arm64@2.6.1: + turbo-windows-arm64@2.6.2: optional: true - turbo@2.6.1: + turbo@2.6.2: optionalDependencies: - turbo-darwin-64: 2.6.1 - turbo-darwin-arm64: 2.6.1 - turbo-linux-64: 2.6.1 - turbo-linux-arm64: 2.6.1 - turbo-windows-64: 2.6.1 - turbo-windows-arm64: 2.6.1 + turbo-darwin-64: 2.6.2 + turbo-darwin-arm64: 2.6.2 + turbo-linux-64: 2.6.2 + turbo-linux-arm64: 2.6.2 + turbo-windows-64: 2.6.2 + turbo-windows-arm64: 2.6.2 turndown@7.2.2: dependencies: @@ -19595,12 +19534,12 @@ snapshots: tunnel: 0.0.6 underscore: 1.13.7 - typescript-eslint@8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3): + typescript-eslint@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) - '@typescript-eslint/parser': 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) - '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.8.3) - '@typescript-eslint/utils': 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/eslint-plugin': 8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/parser': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.48.1(typescript@5.8.3) + '@typescript-eslint/utils': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) eslint: 9.39.1(jiti@2.6.1) typescript: 5.8.3 transitivePeerDependencies: @@ -19748,9 +19687,9 @@ snapshots: readable-stream: 2.3.8 setimmediate: 1.0.5 - update-browserslist-db@1.1.4(browserslist@4.28.0): + update-browserslist-db@1.2.1(browserslist@4.28.1): dependencies: - browserslist: 4.28.0 + browserslist: 4.28.1 escalade: 3.2.0 picocolors: 1.1.1 @@ -19877,13 +19816,13 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite-node@3.2.4(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1): + vite-node@3.2.4(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2): dependencies: cac: 6.7.14 debug: 4.4.3(supports-color@8.1.1) es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + vite: 6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - '@types/node' - jiti @@ -19898,13 +19837,13 @@ snapshots: - tsx - yaml - vite-node@3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1): + vite-node@3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2): dependencies: cac: 6.7.14 debug: 4.4.3(supports-color@8.1.1) es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + vite: 6.3.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - '@types/node' - jiti @@ -19919,9 +19858,9 @@ snapshots: - tsx - yaml - vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1): + vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2): dependencies: - esbuild: 0.27.0 + esbuild: 0.27.1 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 @@ -19932,12 +19871,12 @@ snapshots: fsevents: 2.3.3 jiti: 2.6.1 lightningcss: 1.30.2 - tsx: 4.20.6 - yaml: 2.8.1 + tsx: 4.21.0 + yaml: 2.8.2 - vite@6.3.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1): + vite@6.3.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2): dependencies: - esbuild: 0.27.0 + esbuild: 0.27.1 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 @@ -19948,14 +19887,14 @@ snapshots: fsevents: 2.3.3 jiti: 2.6.1 lightningcss: 1.30.2 - tsx: 4.20.6 - yaml: 2.8.1 + tsx: 4.21.0 + yaml: 2.8.2 - vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1)) + '@vitest/mocker': 3.2.4(vite@6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -19973,8 +19912,8 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) - vite-node: 3.2.4(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + vite: 6.3.6(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vite-node: 3.2.4(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 @@ -19995,11 +19934,11 @@ snapshots: - tsx - yaml - vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.3.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1)) + '@vitest/mocker': 3.2.4(vite@6.3.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -20017,8 +19956,8 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.3.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) - vite-node: 3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + vite: 6.3.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vite-node: 3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 @@ -20230,7 +20169,7 @@ snapshots: yallist@4.0.0: {} - yaml@2.8.1: {} + yaml@2.8.2: {} yargs-parser@18.1.3: dependencies: @@ -20330,6 +20269,6 @@ snapshots: zod@3.25.76: {} - zod@4.1.12: {} + zod@4.1.13: {} zwitch@2.0.4: {} diff --git a/src/api/providers/fetchers/__tests__/vercel-ai-gateway.spec.ts b/src/api/providers/fetchers/__tests__/vercel-ai-gateway.spec.ts index c22cf77002f..d673af65bb6 100644 --- a/src/api/providers/fetchers/__tests__/vercel-ai-gateway.spec.ts +++ b/src/api/providers/fetchers/__tests__/vercel-ai-gateway.spec.ts @@ -108,10 +108,7 @@ describe("Vercel AI Gateway Fetchers", () => { const models = await getVercelAiGatewayModels() expect(models).toEqual({}) - expect(consoleErrorSpy).toHaveBeenCalledWith( - "Vercel AI Gateway models response is invalid", - expect.any(Object), - ) + expect(consoleErrorSpy).toHaveBeenCalled() consoleErrorSpy.mockRestore() }) diff --git a/src/api/providers/fetchers/roo.ts b/src/api/providers/fetchers/roo.ts index 004ff84cc06..615c593a3bc 100644 --- a/src/api/providers/fetchers/roo.ts +++ b/src/api/providers/fetchers/roo.ts @@ -9,8 +9,10 @@ import { DEFAULT_HEADERS } from "../constants" // These override API-provided values for specific models // Exported so RooHandler.getModel() can also apply these for fallback cases export const MODEL_DEFAULTS: Record> = { - "minimax/minimax-m2": { + "minimax/minimax-m2:free": { defaultToolProtocol: "native", + includedTools: ["search_and_replace"], + excludedTools: ["apply_diff"], }, "anthropic/claude-haiku-4.5": { defaultToolProtocol: "native", diff --git a/src/api/providers/fetchers/vercel-ai-gateway.ts b/src/api/providers/fetchers/vercel-ai-gateway.ts index b350e8f2241..c4669ad9048 100644 --- a/src/api/providers/fetchers/vercel-ai-gateway.ts +++ b/src/api/providers/fetchers/vercel-ai-gateway.ts @@ -12,10 +12,11 @@ import { parseApiPrice } from "../../../shared/cost" */ const vercelAiGatewayPricingSchema = z.object({ - input: z.string(), - output: z.string(), + input: z.string().optional(), // Image models don't have an input price. + output: z.string().optional(), // Embedding and image models don't have an output price. input_cache_write: z.string().optional(), input_cache_read: z.string().optional(), + image: z.string().optional(), // Only image models have an image price. }) /** @@ -62,22 +63,19 @@ export async function getVercelAiGatewayModels(options?: ApiHandlerOptions): Pro const data = result.success ? result.data.data : response.data.data if (!result.success) { - console.error("Vercel AI Gateway models response is invalid", result.error.format()) + console.error(`Vercel AI Gateway models response is invalid ${JSON.stringify(result.error.format())}`) } for (const model of data) { const { id } = model - // Only include language models for chat inference - // Embedding models are statically defined in embeddingModels.ts + // Only include language models for chat inference. + // Embedding models are statically defined in embeddingModels.ts. if (model.type !== "language") { continue } - models[id] = parseVercelAiGatewayModel({ - id, - model, - }) + models[id] = parseVercelAiGatewayModel({ id, model }) } } catch (error) { console.warn( diff --git a/src/api/providers/roo.ts b/src/api/providers/roo.ts index 75d2198afb4..4ee41af073c 100644 --- a/src/api/providers/roo.ts +++ b/src/api/providers/roo.ts @@ -38,6 +38,7 @@ function getSessionToken(): string { export class RooHandler extends BaseOpenAiCompatibleProvider { private fetcherBaseURL: string + private currentReasoningDetails: any[] = [] constructor(options: ApiHandlerOptions) { const sessionToken = getSessionToken() @@ -116,12 +117,19 @@ export class RooHandler extends BaseOpenAiCompatibleProvider { } } + getReasoningDetails(): any[] | undefined { + return this.currentReasoningDetails.length > 0 ? this.currentReasoningDetails : undefined + } + override async *createMessage( systemPrompt: string, messages: Anthropic.Messages.MessageParam[], metadata?: ApiHandlerCreateMessageMetadata, ): ApiStream { try { + // Reset reasoning_details accumulator for this request + this.currentReasoningDetails = [] + const headers: Record = { "X-Costrict-App-Version": Package.version, } @@ -133,21 +141,97 @@ export class RooHandler extends BaseOpenAiCompatibleProvider { const stream = await this.createStream(systemPrompt, messages, metadata, { headers }) let lastUsage: RooUsage | undefined = undefined + // Accumulator for reasoning_details: accumulate text by type-index key + const reasoningDetailsAccumulator = new Map< + string, + { + type: string + text?: string + summary?: string + data?: string + id?: string | null + format?: string + signature?: string + index: number + } + >() for await (const chunk of stream) { const delta = chunk.choices[0]?.delta if (delta) { - // Check for reasoning content (similar to OpenRouter) - if ("reasoning" in delta && delta.reasoning && typeof delta.reasoning === "string") { + // Handle reasoning_details array format (used by Gemini 3, Claude, OpenAI o-series, etc.) + // See: https://openrouter.ai/docs/use-cases/reasoning-tokens#preserving-reasoning-blocks + // Priority: Check for reasoning_details first, as it's the newer format + const deltaWithReasoning = delta as typeof delta & { + reasoning_details?: Array<{ + type: string + text?: string + summary?: string + data?: string + id?: string | null + format?: string + signature?: string + index?: number + }> + } + + if (deltaWithReasoning.reasoning_details && Array.isArray(deltaWithReasoning.reasoning_details)) { + for (const detail of deltaWithReasoning.reasoning_details) { + const index = detail.index ?? 0 + const key = `${detail.type}-${index}` + const existing = reasoningDetailsAccumulator.get(key) + + if (existing) { + // Accumulate text/summary/data for existing reasoning detail + if (detail.text !== undefined) { + existing.text = (existing.text || "") + detail.text + } + if (detail.summary !== undefined) { + existing.summary = (existing.summary || "") + detail.summary + } + if (detail.data !== undefined) { + existing.data = (existing.data || "") + detail.data + } + // Update other fields if provided + if (detail.id !== undefined) existing.id = detail.id + if (detail.format !== undefined) existing.format = detail.format + if (detail.signature !== undefined) existing.signature = detail.signature + } else { + // Start new reasoning detail accumulation + reasoningDetailsAccumulator.set(key, { + type: detail.type, + text: detail.text, + summary: detail.summary, + data: detail.data, + id: detail.id, + format: detail.format, + signature: detail.signature, + index, + }) + } + + // Yield text for display (still fragmented for live streaming) + let reasoningText: string | undefined + if (detail.type === "reasoning.text" && typeof detail.text === "string") { + reasoningText = detail.text + } else if (detail.type === "reasoning.summary" && typeof detail.summary === "string") { + reasoningText = detail.summary + } + // Note: reasoning.encrypted types are intentionally skipped as they contain redacted content + + if (reasoningText) { + yield { type: "reasoning", text: reasoningText } + } + } + } else if ("reasoning" in delta && delta.reasoning && typeof delta.reasoning === "string") { + // Handle legacy reasoning format - only if reasoning_details is not present yield { type: "reasoning", text: delta.reasoning, } - } - - // Also check for reasoning_content for backward compatibility - if ("reasoning_content" in delta && typeof delta.reasoning_content === "string") { + } else if ("reasoning_content" in delta && typeof delta.reasoning_content === "string") { + // Also check for reasoning_content for backward compatibility yield { type: "reasoning", text: delta.reasoning_content, @@ -180,6 +264,11 @@ export class RooHandler extends BaseOpenAiCompatibleProvider { } } + // After streaming completes, store the accumulated reasoning_details + if (reasoningDetailsAccumulator.size > 0) { + this.currentReasoningDetails = Array.from(reasoningDetailsAccumulator.values()) + } + if (lastUsage) { // Check if the current model is marked as free const model = this.getModel() diff --git a/src/core/assistant-message/NativeToolCallParser.ts b/src/core/assistant-message/NativeToolCallParser.ts index ac872dddd89..8538a6e3c9c 100644 --- a/src/core/assistant-message/NativeToolCallParser.ts +++ b/src/core/assistant-message/NativeToolCallParser.ts @@ -372,28 +372,6 @@ export class NativeToolCallParser { } break - case "insert_content": - // For partial tool calls, we build nativeArgs incrementally as fields arrive. - // Unlike parseToolCall which validates all required fields, partial parsing - // needs to show progress as each field streams in. - if ( - partialArgs.path !== undefined || - partialArgs.line !== undefined || - partialArgs.content !== undefined - ) { - nativeArgs = { - path: partialArgs.path, - line: - typeof partialArgs.line === "number" - ? partialArgs.line - : partialArgs.line !== undefined - ? parseInt(String(partialArgs.line), 10) - : undefined, - content: partialArgs.content, - } - } - break - case "write_to_file": if (partialArgs.path || partialArgs.content) { nativeArgs = { @@ -619,16 +597,6 @@ export class NativeToolCallParser { } break - case "insert_content": - if (args.path !== undefined && args.line !== undefined && args.content !== undefined) { - nativeArgs = { - path: args.path, - line: typeof args.line === "number" ? args.line : parseInt(String(args.line), 10), - content: args.content, - } as NativeArgsFor - } - break - case "apply_diff": if (args.path !== undefined && args.diff !== undefined) { nativeArgs = { diff --git a/src/core/assistant-message/presentAssistantMessage.ts b/src/core/assistant-message/presentAssistantMessage.ts index fe3aa8ce1e5..43ceeae6144 100644 --- a/src/core/assistant-message/presentAssistantMessage.ts +++ b/src/core/assistant-message/presentAssistantMessage.ts @@ -16,7 +16,6 @@ import { getSimpleReadFileToolDescription, simpleReadFileTool } from "../tools/s import { shouldUseSingleFileRead, TOOL_PROTOCOL } from "@roo-code/types" import { writeToFileTool } from "../tools/WriteToFileTool" import { applyDiffTool } from "../tools/MultiApplyDiffTool" -import { insertContentTool } from "../tools/InsertContentTool" import { searchAndReplaceTool } from "../tools/SearchAndReplaceTool" import { applyPatchTool } from "../tools/ApplyPatchTool" import { listCodeDefinitionNamesTool } from "../tools/ListCodeDefinitionNamesTool" @@ -381,8 +380,6 @@ export async function presentAssistantMessage(cline: Task) { return `[${block.name} for '${block.params.regex}'${ block.params.file_pattern ? ` in '${block.params.file_pattern}'` : "" }]` - case "insert_content": - return `[${block.name} for '${block.params.path}']` case "search_and_replace": return `[${block.name} for '${block.params.path}']` case "apply_patch": @@ -483,16 +480,12 @@ export async function presentAssistantMessage(cline: Task) { const toolCallId = (block as any).id const toolProtocol = toolCallId ? TOOL_PROTOCOL.NATIVE : TOOL_PROTOCOL.XML - // Check experimental setting for multiple native tool calls - const provider = cline.providerRef.deref() - const state = await provider?.getState() - const isMultipleNativeToolCallsEnabled = experiments.isEnabled( - state?.experiments ?? {}, - EXPERIMENT_IDS.MULTIPLE_NATIVE_TOOL_CALLS, - ) + // Multiple native tool calls feature is on hold - always disabled + // Previously resolved from experiments.isEnabled(..., EXPERIMENT_IDS.MULTIPLE_NATIVE_TOOL_CALLS) + const isMultipleNativeToolCallsEnabled = false const pushToolResult = (content: ToolResponse) => { - const editTools = ["insert_content", "apply_diff", "search_and_replace", "apply_patch", "write_to_file"] + const editTools = [/* "insert_content", */ "apply_diff", "search_and_replace", "apply_patch", "write_to_file"] if (toolProtocol === TOOL_PROTOCOL.NATIVE) { // For native protocol, only allow ONE tool_result per tool call if (hasToolResult) { @@ -820,16 +813,6 @@ export async function presentAssistantMessage(cline: Task) { } break } - case "insert_content": - await checkpointSaveAndMark(cline) - await insertContentTool.handle(cline, block as ToolUse<"insert_content">, { - askApproval, - handleError, - pushToolResult, - removeClosingTag, - toolProtocol, - }) - break case "search_and_replace": await checkpointSaveAndMark(cline) await searchAndReplaceTool.handle(cline, block as ToolUse<"search_and_replace">, { diff --git a/src/core/auto-approval/tools.ts b/src/core/auto-approval/tools.ts index e2eae84eef9..a6c76c7173c 100644 --- a/src/core/auto-approval/tools.ts +++ b/src/core/auto-approval/tools.ts @@ -1,7 +1,7 @@ import type { ClineSayTool } from "../../shared/ExtensionMessage" export function isWriteToolAction(tool: ClineSayTool): boolean { - return ["editedExistingFile", "appliedDiff", "newFileCreated", "insertContent", "generateImage"].includes(tool.tool) + return ["editedExistingFile", "appliedDiff", "newFileCreated", "generateImage"].includes(tool.tool) } export function isReadOnlyToolAction(tool: ClineSayTool): boolean { diff --git a/src/core/condense/__tests__/condense.spec.ts b/src/core/condense/__tests__/condense.spec.ts index 5eb97b3e8a3..2558ee5b33a 100644 --- a/src/core/condense/__tests__/condense.spec.ts +++ b/src/core/condense/__tests__/condense.spec.ts @@ -6,7 +6,12 @@ import { TelemetryService } from "@roo-code/telemetry" import { BaseProvider } from "../../../api/providers/base-provider" import { ApiMessage } from "../../task-persistence/apiMessages" -import { summarizeConversation, getMessagesSinceLastSummary, N_MESSAGES_TO_KEEP } from "../index" +import { + summarizeConversation, + getMessagesSinceLastSummary, + getEffectiveApiHistory, + N_MESSAGES_TO_KEEP, +} from "../index" // Create a mock ApiHandler for testing class MockApiHandler extends BaseProvider { @@ -83,11 +88,13 @@ describe("Condense", () => { expect(summaryMessage).toBeTruthy() expect(summaryMessage?.content).toBe("Mock summary of the conversation") - // Verify we have the expected number of messages - // [first message, summary, last N messages] - expect(result.messages.length).toBe(1 + 1 + N_MESSAGES_TO_KEEP) + // With non-destructive condensing, all messages are retained (tagged but not deleted) + // Use getEffectiveApiHistory to verify the effective view matches the old behavior + expect(result.messages.length).toBe(messages.length + 1) // All original messages + summary + const effectiveHistory = getEffectiveApiHistory(result.messages) + expect(effectiveHistory.length).toBe(1 + 1 + N_MESSAGES_TO_KEEP) // first + summary + last N - // Verify the last N messages are preserved + // Verify the last N messages are preserved (same messages by reference) const lastMessages = result.messages.slice(-N_MESSAGES_TO_KEEP) expect(lastMessages).toEqual(messages.slice(-N_MESSAGES_TO_KEEP)) }) diff --git a/src/core/condense/__tests__/index.spec.ts b/src/core/condense/__tests__/index.spec.ts index 4e20a972950..fe17b09ee37 100644 --- a/src/core/condense/__tests__/index.spec.ts +++ b/src/core/condense/__tests__/index.spec.ts @@ -2,6 +2,7 @@ import type { Mock } from "vitest" +import { Anthropic } from "@anthropic-ai/sdk" import { TelemetryService } from "@roo-code/telemetry" import { ApiHandler } from "../../../api" @@ -11,6 +12,8 @@ import { summarizeConversation, getMessagesSinceLastSummary, getKeepMessagesWithToolBlocks, + getEffectiveApiHistory, + cleanupAfterTruncation, N_MESSAGES_TO_KEEP, } from "../index" @@ -407,22 +410,28 @@ describe("summarizeConversation", () => { expect(mockApiHandler.createMessage).toHaveBeenCalled() expect(maybeRemoveImageBlocks).toHaveBeenCalled() - // Verify the structure of the result - // The result should be: first message + summary + last N messages - expect(result.messages.length).toBe(1 + 1 + N_MESSAGES_TO_KEEP) // First + summary + last N + // With non-destructive condensing, the result contains ALL original messages + // plus the summary message. Condensed messages are tagged but not deleted. + // Use getEffectiveApiHistory to verify the effective API view matches the old behavior. + expect(result.messages.length).toBe(messages.length + 1) // All original messages + summary // Check that the first message is preserved expect(result.messages[0]).toEqual(messages[0]) - // Check that the summary message was inserted correctly - const summaryMessage = result.messages[1] - expect(summaryMessage.role).toBe("assistant") - expect(summaryMessage.content).toBe("This is a summary") - expect(summaryMessage.isSummary).toBe(true) + // Find the summary message (it has isSummary: true) + const summaryMessage = result.messages.find((m) => m.isSummary) + expect(summaryMessage).toBeDefined() + expect(summaryMessage!.role).toBe("assistant") + expect(summaryMessage!.content).toBe("This is a summary") + expect(summaryMessage!.isSummary).toBe(true) - // Check that the last N_MESSAGES_TO_KEEP messages are preserved - const lastMessages = messages.slice(-N_MESSAGES_TO_KEEP) - expect(result.messages.slice(-N_MESSAGES_TO_KEEP)).toEqual(lastMessages) + // Verify that the effective API history matches expected: first + summary + last N messages + const effectiveHistory = getEffectiveApiHistory(result.messages) + expect(effectiveHistory.length).toBe(1 + 1 + N_MESSAGES_TO_KEEP) // First + summary + last N + + // Check that condensed messages are properly tagged + const condensedMessages = result.messages.filter((m) => m.condenseParent !== undefined) + expect(condensedMessages.length).toBeGreaterThan(0) // Check the cost and token counts expect(result.cost).toBe(0.05) @@ -643,9 +652,11 @@ describe("summarizeConversation", () => { prevContextTokens, ) - // Should successfully summarize - // Result should be: first message + summary + last N messages - expect(result.messages.length).toBe(1 + 1 + N_MESSAGES_TO_KEEP) // First + summary + last N + // With non-destructive condensing, result contains all messages plus summary + // Use getEffectiveApiHistory to verify the effective API view + expect(result.messages.length).toBe(messages.length + 1) // All messages + summary + const effectiveHistory = getEffectiveApiHistory(result.messages) + expect(effectiveHistory.length).toBe(1 + 1 + N_MESSAGES_TO_KEEP) // First + summary + last N expect(result.cost).toBe(0.03) expect(result.summary).toBe("Concise summary") expect(result.error).toBeUndefined() @@ -809,23 +820,27 @@ describe("summarizeConversation", () => { true, // useNativeTools - required for tool_use block preservation ) - // Verify the summary message has content array with text and tool_use blocks - const summaryMessage = result.messages[1] - expect(summaryMessage.role).toBe("assistant") - expect(summaryMessage.isSummary).toBe(true) - expect(Array.isArray(summaryMessage.content)).toBe(true) + // Find the summary message + const summaryMessage = result.messages.find((m) => m.isSummary) + expect(summaryMessage).toBeDefined() + expect(summaryMessage!.role).toBe("assistant") + expect(summaryMessage!.isSummary).toBe(true) + expect(Array.isArray(summaryMessage!.content)).toBe(true) // Content should be [text block, tool_use block] - const content = summaryMessage.content as any[] + const content = summaryMessage!.content as Anthropic.Messages.ContentBlockParam[] expect(content).toHaveLength(2) expect(content[0].type).toBe("text") - expect(content[0].text).toBe("Summary of conversation") + expect((content[0] as Anthropic.Messages.TextBlockParam).text).toBe("Summary of conversation") expect(content[1].type).toBe("tool_use") - expect(content[1].id).toBe("toolu_123") - expect(content[1].name).toBe("read_file") - - // Verify the keepMessages are preserved correctly - expect(result.messages).toHaveLength(1 + 1 + N_MESSAGES_TO_KEEP) // first + summary + last 3 + expect((content[1] as Anthropic.Messages.ToolUseBlockParam).id).toBe("toolu_123") + expect((content[1] as Anthropic.Messages.ToolUseBlockParam).name).toBe("read_file") + + // With non-destructive condensing, all messages are retained plus the summary + expect(result.messages.length).toBe(messages.length + 1) // all original + summary + // Verify effective history matches expected + const effectiveHistory = getEffectiveApiHistory(result.messages) + expect(effectiveHistory.length).toBe(1 + 1 + N_MESSAGES_TO_KEEP) // first + summary + last 3 expect(result.error).toBeUndefined() }) @@ -961,12 +976,16 @@ describe("summarizeConversation", () => { true, ) - const summaryMessage = result.messages[1] - expect(Array.isArray(summaryMessage.content)).toBe(true) - const summaryContent = summaryMessage.content as any[] + // Find the summary message (it has isSummary: true) + const summaryMessage = result.messages.find((m) => m.isSummary) + expect(summaryMessage).toBeDefined() + expect(Array.isArray(summaryMessage!.content)).toBe(true) + const summaryContent = summaryMessage!.content as Anthropic.Messages.ContentBlockParam[] expect(summaryContent[0]).toEqual({ type: "text", text: "This is a summary" }) - const preservedToolUses = summaryContent.filter((block) => block.type === "tool_use") + const preservedToolUses = summaryContent.filter( + (block): block is Anthropic.Messages.ToolUseBlockParam => block.type === "tool_use", + ) expect(preservedToolUses).toHaveLength(2) expect(preservedToolUses.map((block) => block.id)).toEqual(["toolu_parallel_1", "toolu_parallel_2"]) }) diff --git a/src/core/condense/__tests__/rewind-after-condense.spec.ts b/src/core/condense/__tests__/rewind-after-condense.spec.ts new file mode 100644 index 00000000000..f5f1a09380c --- /dev/null +++ b/src/core/condense/__tests__/rewind-after-condense.spec.ts @@ -0,0 +1,542 @@ +// npx vitest src/core/condense/__tests__/rewind-after-condense.spec.ts + +/** + * Regression tests for the issue: "Rewind after Condense is broken" + * https://github.com/RooCodeInc/Roo-Code/issues/8295 + * + * These tests verify that when a user rewinds (deletes/truncates) their conversation + * after a condense operation, the orphaned condensed messages are properly reactivated + * so they can be sent to the API again. + */ + +import { TelemetryService } from "@roo-code/telemetry" + +import { getEffectiveApiHistory, cleanupAfterTruncation } from "../index" +import { ApiMessage } from "../../task-persistence/apiMessages" + +describe("Rewind After Condense - Issue #8295", () => { + beforeEach(() => { + if (!TelemetryService.hasInstance()) { + TelemetryService.createInstance([]) + } + }) + + describe("getEffectiveApiHistory", () => { + it("should filter out messages tagged with condenseParent", () => { + const condenseId = "summary-123" + const messages: ApiMessage[] = [ + { role: "user", content: "First message", ts: 1 }, + { role: "assistant", content: "First response", ts: 2, condenseParent: condenseId }, + { role: "user", content: "Second message", ts: 3, condenseParent: condenseId }, + { role: "assistant", content: "Summary", ts: 4, isSummary: true, condenseId }, + { role: "user", content: "Third message", ts: 5 }, + { role: "assistant", content: "Third response", ts: 6 }, + ] + + const effective = getEffectiveApiHistory(messages) + + // Effective history should be: first message, summary, third message, third response + expect(effective.length).toBe(4) + expect(effective[0].content).toBe("First message") + expect(effective[1].isSummary).toBe(true) + expect(effective[2].content).toBe("Third message") + expect(effective[3].content).toBe("Third response") + }) + + it("should include messages without condenseParent", () => { + const messages: ApiMessage[] = [ + { role: "user", content: "Hello", ts: 1 }, + { role: "assistant", content: "Hi", ts: 2 }, + ] + + const effective = getEffectiveApiHistory(messages) + + expect(effective.length).toBe(2) + expect(effective).toEqual(messages) + }) + + it("should handle empty messages array", () => { + const effective = getEffectiveApiHistory([]) + expect(effective).toEqual([]) + }) + }) + + describe("cleanupAfterTruncation", () => { + it("should clear condenseParent when summary message is deleted", () => { + const condenseId = "summary-123" + const messages: ApiMessage[] = [ + { role: "user", content: "First message", ts: 1 }, + { role: "assistant", content: "First response", ts: 2, condenseParent: condenseId }, + { role: "user", content: "Second message", ts: 3, condenseParent: condenseId }, + // Summary is NOT in the array (was truncated/deleted) + ] + + const cleaned = cleanupAfterTruncation(messages) + + // All condenseParent tags should be cleared since summary is gone + expect(cleaned[1].condenseParent).toBeUndefined() + expect(cleaned[2].condenseParent).toBeUndefined() + }) + + it("should preserve condenseParent when summary message still exists", () => { + const condenseId = "summary-123" + const messages: ApiMessage[] = [ + { role: "user", content: "First message", ts: 1 }, + { role: "assistant", content: "First response", ts: 2, condenseParent: condenseId }, + { role: "assistant", content: "Summary", ts: 3, isSummary: true, condenseId }, + ] + + const cleaned = cleanupAfterTruncation(messages) + + // condenseParent should remain since summary exists + expect(cleaned[1].condenseParent).toBe(condenseId) + }) + + it("should handle multiple condense operations with different IDs", () => { + const condenseId1 = "summary-1" + const condenseId2 = "summary-2" + const messages: ApiMessage[] = [ + { role: "user", content: "Message 1", ts: 1, condenseParent: condenseId1 }, + { role: "assistant", content: "Summary 1", ts: 2, isSummary: true, condenseId: condenseId1 }, + { role: "user", content: "Message 2", ts: 3, condenseParent: condenseId2 }, + // Summary 2 is NOT present (was truncated) + ] + + const cleaned = cleanupAfterTruncation(messages) + + // condenseId1 should remain (summary exists) + expect(cleaned[0].condenseParent).toBe(condenseId1) + // condenseId2 should be cleared (summary deleted) + expect(cleaned[2].condenseParent).toBeUndefined() + }) + + it("should not modify messages without condenseParent", () => { + const messages: ApiMessage[] = [ + { role: "user", content: "Hello", ts: 1 }, + { role: "assistant", content: "Hi", ts: 2 }, + ] + + const cleaned = cleanupAfterTruncation(messages) + + expect(cleaned).toEqual(messages) + }) + + it("should handle empty messages array", () => { + const cleaned = cleanupAfterTruncation([]) + expect(cleaned).toEqual([]) + }) + }) + + describe("Rewind scenario: truncate after condense", () => { + it("should reactivate condensed messages when their summary is deleted via truncation", () => { + const condenseId = "summary-abc" + + // Simulate a conversation after condensing + const fullHistory: ApiMessage[] = [ + { role: "user", content: "Initial task", ts: 1 }, + { role: "assistant", content: "Working on it", ts: 2, condenseParent: condenseId }, + { role: "user", content: "Continue", ts: 3, condenseParent: condenseId }, + { role: "assistant", content: "Summary of work so far", ts: 4, isSummary: true, condenseId }, + { role: "user", content: "Now do this", ts: 5 }, + { role: "assistant", content: "Done", ts: 6 }, + { role: "user", content: "And this", ts: 7 }, + { role: "assistant", content: "Also done", ts: 8 }, + ] + + // Verify effective history before truncation + const effectiveBefore = getEffectiveApiHistory(fullHistory) + // Should be: first message, summary, last 4 messages + expect(effectiveBefore.length).toBe(6) + + // Simulate rewind: user truncates back to message ts=4 (keeping 0-3) + const truncatedHistory = fullHistory.slice(0, 4) // Keep first, condensed1, condensed2, summary + + // After truncation, the summary is still there, so condensed messages remain condensed + const cleanedAfterKeepingSummary = cleanupAfterTruncation(truncatedHistory) + expect(cleanedAfterKeepingSummary[1].condenseParent).toBe(condenseId) + expect(cleanedAfterKeepingSummary[2].condenseParent).toBe(condenseId) + + // Now simulate a more aggressive rewind: delete back to message ts=2 + const aggressiveTruncate = fullHistory.slice(0, 2) // Keep only first message and first response + + // The condensed messages should now be reactivated since summary is gone + const cleanedAfterDeletingSummary = cleanupAfterTruncation(aggressiveTruncate) + expect(cleanedAfterDeletingSummary[1].condenseParent).toBeUndefined() + + // Verify effective history after cleanup + const effectiveAfterCleanup = getEffectiveApiHistory(cleanedAfterDeletingSummary) + // Now both messages should be active (no condensed filtering) + expect(effectiveAfterCleanup.length).toBe(2) + expect(effectiveAfterCleanup[0].content).toBe("Initial task") + expect(effectiveAfterCleanup[1].content).toBe("Working on it") + }) + + it("should properly restore context after rewind when summary was deleted", () => { + const condenseId = "summary-xyz" + + // Scenario: Most of the conversation was condensed, but the summary was deleted. + // getEffectiveApiHistory already correctly handles orphaned messages (includes them + // when their summary doesn't exist). cleanupAfterTruncation cleans up the tags. + const messages: ApiMessage[] = [ + { role: "user", content: "Start", ts: 1 }, + { role: "assistant", content: "Response 1", ts: 2, condenseParent: condenseId }, + { role: "user", content: "More", ts: 3, condenseParent: condenseId }, + { role: "assistant", content: "Response 2", ts: 4, condenseParent: condenseId }, + { role: "user", content: "Even more", ts: 5, condenseParent: condenseId }, + // Summary was deleted (not present), so these are "orphaned" messages + ] + + // getEffectiveApiHistory already includes orphaned messages (summary doesn't exist) + const effectiveBefore = getEffectiveApiHistory(messages) + expect(effectiveBefore.length).toBe(5) // All messages visible since summary was deleted + expect(effectiveBefore[0].content).toBe("Start") + expect(effectiveBefore[1].content).toBe("Response 1") + + // cleanupAfterTruncation clears the orphaned condenseParent tags for data hygiene + const cleaned = cleanupAfterTruncation(messages) + + // Verify condenseParent was cleared for all orphaned messages + expect(cleaned[1].condenseParent).toBeUndefined() + expect(cleaned[2].condenseParent).toBeUndefined() + expect(cleaned[3].condenseParent).toBeUndefined() + expect(cleaned[4].condenseParent).toBeUndefined() + + // After cleanup, effective history is the same (all visible) + const effectiveAfter = getEffectiveApiHistory(cleaned) + expect(effectiveAfter.length).toBe(5) // All messages visible + }) + + it("should hide condensed messages when their summary still exists", () => { + const condenseId = "summary-exists" + + // Scenario: Messages were condensed and summary exists - condensed messages should be hidden + const messages: ApiMessage[] = [ + { role: "user", content: "Start", ts: 1 }, + { role: "assistant", content: "Response 1", ts: 2, condenseParent: condenseId }, + { role: "user", content: "More", ts: 3, condenseParent: condenseId }, + { role: "assistant", content: "Summary", ts: 4, isSummary: true, condenseId }, + { role: "user", content: "After summary", ts: 5 }, + ] + + // Effective history should hide condensed messages since summary exists + const effective = getEffectiveApiHistory(messages) + expect(effective.length).toBe(3) // Start, Summary, After summary + expect(effective[0].content).toBe("Start") + expect(effective[1].content).toBe("Summary") + expect(effective[2].content).toBe("After summary") + + // cleanupAfterTruncation should NOT clear condenseParent since summary exists + const cleaned = cleanupAfterTruncation(messages) + expect(cleaned[1].condenseParent).toBe(condenseId) + expect(cleaned[2].condenseParent).toBe(condenseId) + }) + + describe("Summary timestamp collision prevention", () => { + it("should give summary a unique timestamp that does not collide with first kept message", () => { + // Scenario: After condense, the summary message should have a unique timestamp + // (ts - 1 from the first kept message) to prevent lookup collisions. + // + // This test verifies the expected data structure after condense: + // - Summary should have ts = firstKeptMessage.ts - 1 + // - Summary and first kept message should NOT share the same timestamp + // + // With real millisecond timestamps, the summary timestamp (firstKeptTs - 1) will + // never collide with an existing message since timestamps are always increasing. + + const condenseId = "summary-unique-ts" + // Use timestamps that represent a realistic scenario where firstKeptTs - 1 + // does not collide with any existing message timestamp + const firstKeptTs = 1000 + + // Simulate post-condense state where summary has unique timestamp (firstKeptTs - 1) + // In real usage, condensed messages have timestamps like 100, 200, 300... + // and firstKeptTs is much larger, so firstKeptTs - 1 = 999 is unique + const messagesAfterCondense: ApiMessage[] = [ + { role: "user", content: "Initial task", ts: 100 }, + { role: "assistant", content: "Response 1", ts: 200, condenseParent: condenseId }, + { role: "user", content: "Continue", ts: 300, condenseParent: condenseId }, + { role: "assistant", content: "Response 2", ts: 400, condenseParent: condenseId }, + { role: "user", content: "More work", ts: 500, condenseParent: condenseId }, + { role: "assistant", content: "Response 3", ts: 600, condenseParent: condenseId }, + { role: "user", content: "Even more", ts: 700, condenseParent: condenseId }, + // Summary gets ts = firstKeptTs - 1 = 999, which is unique + { role: "assistant", content: "Summary", ts: firstKeptTs - 1, isSummary: true, condenseId }, + // First kept message + { role: "user", content: "First kept message", ts: firstKeptTs }, + { role: "assistant", content: "Response to first kept", ts: 1100 }, + { role: "user", content: "Last message", ts: 1200 }, + ] + + // Find all messages with the same timestamp as the summary + const summaryTs = firstKeptTs - 1 + const messagesWithSummaryTs = messagesAfterCondense.filter((msg) => msg.ts === summaryTs) + + // There should be exactly one message with the summary timestamp + expect(messagesWithSummaryTs.length).toBe(1) + expect(messagesWithSummaryTs[0].isSummary).toBe(true) + + // The first kept message should have a different timestamp + const firstKeptMessage = messagesAfterCondense.find( + (msg) => msg.ts === firstKeptTs && !msg.isSummary && !msg.condenseParent, + ) + expect(firstKeptMessage).toBeDefined() + expect(firstKeptMessage?.content).toBe("First kept message") + expect(firstKeptMessage?.ts).not.toBe(summaryTs) + }) + + it("should not target summary message when looking up first kept message by timestamp", () => { + // This test verifies that when timestamps are unique (as they should be after the fix), + // looking up by the first kept message's timestamp returns that message, not the summary. + + const condenseId = "summary-lookup-test" + const firstKeptTs = 8 + + const messages: ApiMessage[] = [ + { role: "user", content: "Initial", ts: 1 }, + { role: "assistant", content: "Summary", ts: firstKeptTs - 1, isSummary: true, condenseId }, + { role: "user", content: "First kept message", ts: firstKeptTs }, + { role: "assistant", content: "Response", ts: 9 }, + ] + + // Look up by first kept message's timestamp + const foundMessage = messages.find((msg) => msg.ts === firstKeptTs) + expect(foundMessage).toBeDefined() + expect(foundMessage?.content).toBe("First kept message") + expect(foundMessage?.isSummary).toBeUndefined() + + // Looking up by summary's timestamp should find the summary + const foundSummary = messages.find((msg) => msg.ts === firstKeptTs - 1) + expect(foundSummary).toBeDefined() + expect(foundSummary?.isSummary).toBe(true) + }) + }) + + describe("Message preservation after condense operations", () => { + /** + * These tests verify that the correct user and assistant messages are preserved + * and sent to the LLM after condense operations. With N_MESSAGES_TO_KEEP = 3, + * condense should always preserve: + * - The first message (never condensed) + * - The active summary + * - The last 3 kept messages + */ + + it("should preserve correct messages after single condense (10 messages)", () => { + const condenseId = "summary-single" + + // Simulate storage state after condensing 10 messages with N_MESSAGES_TO_KEEP = 3 + // Original: [msg1, msg2, msg3, msg4, msg5, msg6, msg7, msg8, msg9, msg10] + // After condense: + // - msg1 preserved (first message) + // - msg2-msg7 tagged with condenseParent + // - summary inserted with ts = msg8.ts - 1 + // - msg8, msg9, msg10 kept + const storageAfterCondense: ApiMessage[] = [ + { role: "user", content: "Task: Build a feature", ts: 100 }, + { role: "assistant", content: "I'll help with that", ts: 200, condenseParent: condenseId }, + { role: "user", content: "Start with the API", ts: 300, condenseParent: condenseId }, + { role: "assistant", content: "Creating API endpoints", ts: 400, condenseParent: condenseId }, + { role: "user", content: "Add validation", ts: 500, condenseParent: condenseId }, + { role: "assistant", content: "Added validation logic", ts: 600, condenseParent: condenseId }, + { role: "user", content: "Now the tests", ts: 700, condenseParent: condenseId }, + // Summary inserted before first kept message + { + role: "assistant", + content: "Summary: Built API with validation, working on tests", + ts: 799, // msg8.ts - 1 + isSummary: true, + condenseId, + }, + // Last 3 kept messages (N_MESSAGES_TO_KEEP = 3) + { role: "assistant", content: "Writing unit tests now", ts: 800 }, + { role: "user", content: "Include edge cases", ts: 900 }, + { role: "assistant", content: "Added edge case tests", ts: 1000 }, + ] + + const effective = getEffectiveApiHistory(storageAfterCondense) + + // Should send exactly 5 messages to LLM: + // 1. First message (user) - preserved + // 2. Summary (assistant) + // 3-5. Last 3 kept messages + expect(effective.length).toBe(5) + + // Verify exact order and content + expect(effective[0].role).toBe("user") + expect(effective[0].content).toBe("Task: Build a feature") + + expect(effective[1].role).toBe("assistant") + expect(effective[1].isSummary).toBe(true) + expect(effective[1].content).toBe("Summary: Built API with validation, working on tests") + + expect(effective[2].role).toBe("assistant") + expect(effective[2].content).toBe("Writing unit tests now") + + expect(effective[3].role).toBe("user") + expect(effective[3].content).toBe("Include edge cases") + + expect(effective[4].role).toBe("assistant") + expect(effective[4].content).toBe("Added edge case tests") + + // Verify condensed messages are NOT in effective history + const condensedContents = ["I'll help with that", "Start with the API", "Creating API endpoints"] + for (const content of condensedContents) { + expect(effective.find((m) => m.content === content)).toBeUndefined() + } + }) + + it("should preserve correct messages after double condense (10 msgs → condense → 10 more msgs → condense)", () => { + const condenseId1 = "summary-first" + const condenseId2 = "summary-second" + + // Simulate storage state after TWO condense operations + // First condense: 10 messages condensed, summary1 created + // Then: 10 more messages added (making effective history have 15 messages) + // Second condense: summary1 + msg8-msg17 condensed, summary2 created + // + // Storage after double condense: + const storageAfterDoubleCondense: ApiMessage[] = [ + // First message - never condensed + { role: "user", content: "Initial task: Build a full app", ts: 100 }, + + // Messages from first condense (tagged with condenseId1) + { role: "assistant", content: "Starting the project", ts: 200, condenseParent: condenseId1 }, + { role: "user", content: "Add authentication", ts: 300, condenseParent: condenseId1 }, + { role: "assistant", content: "Added auth module", ts: 400, condenseParent: condenseId1 }, + { role: "user", content: "Add database", ts: 500, condenseParent: condenseId1 }, + { role: "assistant", content: "Set up database", ts: 600, condenseParent: condenseId1 }, + { role: "user", content: "Connect them", ts: 700, condenseParent: condenseId1 }, + + // First summary - now ALSO tagged with condenseId2 (from second condense) + { + role: "assistant", + content: "Summary1: Built auth and database", + ts: 799, + isSummary: true, + condenseId: condenseId1, + condenseParent: condenseId2, // Tagged during second condense! + }, + + // Messages after first condense but before second (tagged with condenseId2) + { role: "assistant", content: "Continuing development", ts: 800, condenseParent: condenseId2 }, + { role: "user", content: "Add API routes", ts: 900, condenseParent: condenseId2 }, + { role: "assistant", content: "Created REST endpoints", ts: 1000, condenseParent: condenseId2 }, + { role: "user", content: "Add validation", ts: 1100, condenseParent: condenseId2 }, + { role: "assistant", content: "Added input validation", ts: 1200, condenseParent: condenseId2 }, + { role: "user", content: "Add error handling", ts: 1300, condenseParent: condenseId2 }, + { role: "assistant", content: "Implemented error handlers", ts: 1400, condenseParent: condenseId2 }, + { role: "user", content: "Add logging", ts: 1500, condenseParent: condenseId2 }, + { role: "assistant", content: "Set up logging system", ts: 1600, condenseParent: condenseId2 }, + { role: "user", content: "Now write tests", ts: 1700, condenseParent: condenseId2 }, + + // Second summary - inserted before the last 3 kept messages + { + role: "assistant", + content: "Summary2: App complete with auth, DB, API, validation, errors, logging. Now testing.", + ts: 1799, // msg18.ts - 1 + isSummary: true, + condenseId: condenseId2, + }, + + // Last 3 kept messages (N_MESSAGES_TO_KEEP = 3) + { role: "assistant", content: "Writing integration tests", ts: 1800 }, + { role: "user", content: "Test the auth flow", ts: 1900 }, + { role: "assistant", content: "Auth tests passing", ts: 2000 }, + ] + + const effective = getEffectiveApiHistory(storageAfterDoubleCondense) + + // Should send exactly 5 messages to LLM: + // 1. First message (user) - preserved + // 2. Summary2 (assistant) - the ACTIVE summary + // 3-5. Last 3 kept messages + expect(effective.length).toBe(5) + + // Verify exact order and content + expect(effective[0].role).toBe("user") + expect(effective[0].content).toBe("Initial task: Build a full app") + + expect(effective[1].role).toBe("assistant") + expect(effective[1].isSummary).toBe(true) + expect(effective[1].condenseId).toBe(condenseId2) // Must be the SECOND summary + expect(effective[1].content).toContain("Summary2") + + expect(effective[2].role).toBe("assistant") + expect(effective[2].content).toBe("Writing integration tests") + + expect(effective[3].role).toBe("user") + expect(effective[3].content).toBe("Test the auth flow") + + expect(effective[4].role).toBe("assistant") + expect(effective[4].content).toBe("Auth tests passing") + + // Verify Summary1 is NOT in effective history (it's tagged with condenseParent) + const summary1 = effective.find((m) => m.content?.toString().includes("Summary1")) + expect(summary1).toBeUndefined() + + // Verify all condensed messages are NOT in effective history + const condensedContents = [ + "Starting the project", + "Added auth module", + "Continuing development", + "Created REST endpoints", + "Implemented error handlers", + ] + for (const content of condensedContents) { + expect(effective.find((m) => m.content === content)).toBeUndefined() + } + }) + + it("should maintain proper user/assistant alternation in effective history", () => { + const condenseId = "summary-alternation" + + // Verify that after condense, the effective history maintains proper + // user/assistant message alternation (important for API compatibility) + const storage: ApiMessage[] = [ + { role: "user", content: "Start task", ts: 100 }, + { role: "assistant", content: "Response 1", ts: 200, condenseParent: condenseId }, + { role: "user", content: "Continue", ts: 300, condenseParent: condenseId }, + { role: "assistant", content: "Summary text", ts: 399, isSummary: true, condenseId }, + // Kept messages - should alternate properly + { role: "assistant", content: "Response after summary", ts: 400 }, + { role: "user", content: "User message", ts: 500 }, + { role: "assistant", content: "Final response", ts: 600 }, + ] + + const effective = getEffectiveApiHistory(storage) + + // Verify the sequence: user, assistant(summary), assistant, user, assistant + // Note: Having two assistant messages in a row (summary + next response) is valid + // because the summary replaces what would have been multiple messages + expect(effective[0].role).toBe("user") + expect(effective[1].role).toBe("assistant") + expect(effective[1].isSummary).toBe(true) + expect(effective[2].role).toBe("assistant") + expect(effective[3].role).toBe("user") + expect(effective[4].role).toBe("assistant") + }) + + it("should preserve timestamps in chronological order in effective history", () => { + const condenseId = "summary-timestamps" + + const storage: ApiMessage[] = [ + { role: "user", content: "First", ts: 100 }, + { role: "assistant", content: "Condensed", ts: 200, condenseParent: condenseId }, + { role: "assistant", content: "Summary", ts: 299, isSummary: true, condenseId }, + { role: "user", content: "Kept 1", ts: 300 }, + { role: "assistant", content: "Kept 2", ts: 400 }, + { role: "user", content: "Kept 3", ts: 500 }, + ] + + const effective = getEffectiveApiHistory(storage) + + // Verify timestamps are in ascending order + for (let i = 1; i < effective.length; i++) { + const prevTs = effective[i - 1].ts ?? 0 + const currTs = effective[i].ts ?? 0 + expect(currTs).toBeGreaterThan(prevTs) + } + }) + }) + }) +}) diff --git a/src/core/condense/index.ts b/src/core/condense/index.ts index d330716df10..b8af4d1de24 100644 --- a/src/core/condense/index.ts +++ b/src/core/condense/index.ts @@ -1,4 +1,5 @@ import Anthropic from "@anthropic-ai/sdk" +import crypto from "crypto" import { TelemetryService } from "@roo-code/telemetry" @@ -117,6 +118,7 @@ export type SummarizeResponse = { cost: number // The cost of the summarization operation newContextTokens?: number // The number of tokens in the context for the next API request error?: string // Populated iff the operation fails: error message shown to the user on failure (see Task.ts) + condenseId?: string // The unique ID of the created Summary message, for linking to condense_context clineMessage } /** @@ -266,15 +268,51 @@ export async function summarizeConversation( summaryContent = summary } + // Generate a unique condenseId for this summary + const condenseId = crypto.randomUUID() + + // Use first kept message's timestamp minus 1 to ensure unique timestamp for summary. + // Fallback to Date.now() if keepMessages is empty (shouldn't happen due to earlier checks). + const firstKeptTs = keepMessages[0]?.ts ?? Date.now() + const summaryMessage: ApiMessage = { role: "assistant", content: summaryContent, - ts: keepMessages[0].ts, + ts: firstKeptTs - 1, // Unique timestamp before first kept message to avoid collision isSummary: true, + condenseId, // Unique ID for this summary, used to track which messages it replaces } - // Reconstruct messages: [first message, summary, last N messages] - const newMessages = [firstMessage, summaryMessage, ...keepMessages] + // NON-DESTRUCTIVE CONDENSE: + // Instead of deleting middle messages, tag them with condenseParent so they can be + // restored if the user rewinds to a point before the summary. + // + // Storage structure after condense: + // [firstMessage, msg2(parent=X), ..., msg8(parent=X), summary(id=X), msg9, msg10, msg11] + // + // Effective for API (filtered by getEffectiveApiHistory): + // [firstMessage, summary, msg9, msg10, msg11] + + // Tag middle messages with condenseParent (skip first message, skip last N messages) + const newMessages = messages.map((msg, index) => { + // First message stays as-is + if (index === 0) { + return msg + } + // Messages in the "keep" range stay as-is + if (index >= keepStartIndex) { + return msg + } + // Middle messages get tagged with condenseParent (unless they already have one from a previous condense) + // If they already have a condenseParent, we leave it - nested condense is handled by filtering + if (!msg.condenseParent) { + return { ...msg, condenseParent: condenseId } + } + return msg + }) + + // Insert the summary message right before the keep messages + newMessages.splice(keepStartIndex, 0, summaryMessage) // Count the tokens in the context for the next API request // We only estimate the tokens in summaryMesage if outputTokens is 0, otherwise we use outputTokens @@ -293,7 +331,7 @@ export async function summarizeConversation( const error = t("common:errors.condense_context_grew") return { ...response, cost, error } } - return { messages: newMessages, summary, cost, newContextTokens } + return { messages: newMessages, summary, cost, newContextTokens, condenseId } } /* Returns the list of all messages since the last summary message, including the summary. Returns all messages if there is no summary. */ @@ -329,3 +367,108 @@ export function getMessagesSinceLastSummary(messages: ApiMessage[]): ApiMessage[ return messagesSinceSummary } + +/** + * Filters the API conversation history to get the "effective" messages to send to the API. + * Messages with a condenseParent that points to an existing summary are filtered out, + * as they have been replaced by that summary. + * Messages with a truncationParent that points to an existing truncation marker are also filtered out, + * as they have been hidden by sliding window truncation. + * + * This allows non-destructive condensing and truncation where messages are tagged but not deleted, + * enabling accurate rewind operations while still sending condensed/truncated history to the API. + * + * @param messages - The full API conversation history including tagged messages + * @returns The filtered history that should be sent to the API + */ +export function getEffectiveApiHistory(messages: ApiMessage[]): ApiMessage[] { + // Collect all condenseIds of summaries that exist in the current history + const existingSummaryIds = new Set() + // Collect all truncationIds of truncation markers that exist in the current history + const existingTruncationIds = new Set() + + for (const msg of messages) { + if (msg.isSummary && msg.condenseId) { + existingSummaryIds.add(msg.condenseId) + } + if (msg.isTruncationMarker && msg.truncationId) { + existingTruncationIds.add(msg.truncationId) + } + } + + // Filter out messages whose condenseParent points to an existing summary + // or whose truncationParent points to an existing truncation marker. + // Messages with orphaned parents (summary/marker was deleted) are included + return messages.filter((msg) => { + // Filter out condensed messages if their summary exists + if (msg.condenseParent && existingSummaryIds.has(msg.condenseParent)) { + return false + } + // Filter out truncated messages if their truncation marker exists + if (msg.truncationParent && existingTruncationIds.has(msg.truncationParent)) { + return false + } + return true + }) +} + +/** + * Cleans up orphaned condenseParent and truncationParent references after a truncation operation (rewind/delete). + * When a summary message or truncation marker is deleted, messages that were tagged with its ID + * should have their parent reference cleared so they become active again. + * + * This function should be called after any operation that truncates the API history + * to ensure messages are properly restored when their summary or truncation marker is deleted. + * + * @param messages - The API conversation history after truncation + * @returns The cleaned history with orphaned condenseParent and truncationParent fields cleared + */ +export function cleanupAfterTruncation(messages: ApiMessage[]): ApiMessage[] { + // Collect all condenseIds of summaries that still exist + const existingSummaryIds = new Set() + // Collect all truncationIds of truncation markers that still exist + const existingTruncationIds = new Set() + + for (const msg of messages) { + if (msg.isSummary && msg.condenseId) { + existingSummaryIds.add(msg.condenseId) + } + if (msg.isTruncationMarker && msg.truncationId) { + existingTruncationIds.add(msg.truncationId) + } + } + + // Clear orphaned parent references for messages whose summary or truncation marker was deleted + return messages.map((msg) => { + let needsUpdate = false + + // Check for orphaned condenseParent + if (msg.condenseParent && !existingSummaryIds.has(msg.condenseParent)) { + needsUpdate = true + } + + // Check for orphaned truncationParent + if (msg.truncationParent && !existingTruncationIds.has(msg.truncationParent)) { + needsUpdate = true + } + + if (needsUpdate) { + // Create a new object without orphaned parent references + const { condenseParent, truncationParent, ...rest } = msg + const result: ApiMessage = rest as ApiMessage + + // Keep condenseParent if its summary still exists + if (condenseParent && existingSummaryIds.has(condenseParent)) { + result.condenseParent = condenseParent + } + + // Keep truncationParent if its truncation marker still exists + if (truncationParent && existingTruncationIds.has(truncationParent)) { + result.truncationParent = truncationParent + } + + return result + } + return msg + }) +} diff --git a/src/core/context-management/__tests__/context-management.spec.ts b/src/core/context-management/__tests__/context-management.spec.ts index 712785b7cd8..308d0e2e965 100644 --- a/src/core/context-management/__tests__/context-management.spec.ts +++ b/src/core/context-management/__tests__/context-management.spec.ts @@ -65,10 +65,14 @@ describe("Context Management", () => { // With 2 messages after the first, 0.5 fraction means remove 1 message // But 1 is odd, so it rounds down to 0 (to make it even) - expect(result.length).toBe(3) // First message + 2 remaining messages - expect(result[0]).toEqual(messages[0]) - expect(result[1]).toEqual(messages[1]) - expect(result[2]).toEqual(messages[2]) + // Result should have messages + truncation marker + expect(result.messages.length).toBe(4) // First message + truncation marker + 2 remaining messages + expect(result.messages[0]).toEqual(messages[0]) + // messages[1] is the truncation marker + expect(result.messages[1].isTruncationMarker).toBe(true) + // Original messages[1] and messages[2] are at indices 2 and 3 now + expect(result.messages[2].content).toEqual(messages[1].content) + expect(result.messages[3].content).toEqual(messages[2].content) }) it("should remove the specified fraction of messages (rounded to even number)", () => { @@ -84,10 +88,17 @@ describe("Context Management", () => { // 2 is already even, so no rounding needed const result = truncateConversation(messages, 0.5, taskId) - expect(result.length).toBe(3) - expect(result[0]).toEqual(messages[0]) - expect(result[1]).toEqual(messages[3]) - expect(result[2]).toEqual(messages[4]) + // Should have all original messages + truncation marker + expect(result.messages.length).toBe(6) // 5 original + 1 marker + expect(result.messagesRemoved).toBe(2) + expect(result.messages[0]).toEqual(messages[0]) + expect(result.messages[1].isTruncationMarker).toBe(true) + // Messages 2 and 3 (indices 1 and 2 from original) should be tagged + expect(result.messages[2].truncationParent).toBe(result.truncationId) + expect(result.messages[3].truncationParent).toBe(result.truncationId) + // Messages 4 and 5 (indices 3 and 4 from original) should NOT be tagged + expect(result.messages[4].truncationParent).toBeUndefined() + expect(result.messages[5].truncationParent).toBeUndefined() }) it("should round to an even number of messages to remove", () => { @@ -105,8 +116,10 @@ describe("Context Management", () => { // 1.8 rounds down to 1, then to 0 to make it even const result = truncateConversation(messages, 0.3, taskId) - expect(result.length).toBe(7) // No messages removed - expect(result).toEqual(messages) + expect(result.messagesRemoved).toBe(0) // No messages removed + // Should still have truncation marker inserted + expect(result.messages.length).toBe(8) // 7 original + 1 marker + expect(result.messages[1].isTruncationMarker).toBe(true) }) it("should handle edge case with fracToRemove = 0", () => { @@ -118,7 +131,10 @@ describe("Context Management", () => { const result = truncateConversation(messages, 0, taskId) - expect(result).toEqual(messages) + expect(result.messagesRemoved).toBe(0) + // Should have original messages + truncation marker + expect(result.messages.length).toBe(4) + expect(result.messages[1].isTruncationMarker).toBe(true) }) it("should handle edge case with fracToRemove = 1", () => { @@ -133,9 +149,16 @@ describe("Context Management", () => { // But 3 is odd, so it rounds down to 2 to make it even const result = truncateConversation(messages, 1, taskId) - expect(result.length).toBe(2) - expect(result[0]).toEqual(messages[0]) - expect(result[1]).toEqual(messages[3]) + expect(result.messagesRemoved).toBe(2) + // Should have all original messages + truncation marker + expect(result.messages.length).toBe(5) // 4 original + 1 marker + expect(result.messages[0]).toEqual(messages[0]) + expect(result.messages[1].isTruncationMarker).toBe(true) + // Messages at indices 2 and 3 should be tagged (original indices 1 and 2) + expect(result.messages[2].truncationParent).toBe(result.truncationId) + expect(result.messages[3].truncationParent).toBe(result.truncationId) + // Last message should NOT be tagged + expect(result.messages[4].truncationParent).toBeUndefined() }) }) @@ -289,14 +312,6 @@ describe("Context Management", () => { { ...messages[messages.length - 1], content: "" }, ] - // When truncating, always uses 0.5 fraction - // With 4 messages after the first, 0.5 fraction means remove 2 messages - const expectedMessages = [ - messagesWithSmallContent[0], - messagesWithSmallContent[3], - messagesWithSmallContent[4], - ] - const result = await manageContext({ messages: messagesWithSmallContent, totalTokens, @@ -311,12 +326,14 @@ describe("Context Management", () => { currentProfileId: "default", }) - expect(result).toEqual({ - messages: expectedMessages, - summary: "", - cost: 0, - prevContextTokens: totalTokens, - }) + // Should have truncation + expect(result.truncationId).toBeDefined() + expect(result.messagesRemoved).toBe(2) // With 4 messages after first, 0.5 fraction = 2 to remove + expect(result.summary).toBe("") + expect(result.cost).toBe(0) + expect(result.prevContextTokens).toBe(totalTokens) + // Should have all original messages + truncation marker (non-destructive) + expect(result.messages.length).toBe(6) // 5 original + 1 marker }) it("should work with non-prompt caching models the same as prompt caching models", async () => { @@ -360,10 +377,14 @@ describe("Context Management", () => { currentProfileId: "default", }) - expect(result1.messages).toEqual(result2.messages) + // For truncation results, we can't compare messages directly because + // truncationId is randomly generated. Compare structure instead. + expect(result1.messages.length).toEqual(result2.messages.length) expect(result1.summary).toEqual(result2.summary) expect(result1.cost).toEqual(result2.cost) expect(result1.prevContextTokens).toEqual(result2.prevContextTokens) + expect(result1.truncationId).toBeDefined() + expect(result2.truncationId).toBeDefined() // Test above threshold const aboveThreshold = 70001 @@ -395,10 +416,14 @@ describe("Context Management", () => { currentProfileId: "default", }) - expect(result3.messages).toEqual(result4.messages) + // For truncation results, we can't compare messages directly because + // truncationId is randomly generated. Compare structure instead. + expect(result3.messages.length).toEqual(result4.messages.length) expect(result3.summary).toEqual(result4.summary) expect(result3.cost).toEqual(result4.cost) expect(result3.prevContextTokens).toEqual(result4.prevContextTokens) + expect(result3.truncationId).toBeDefined() + expect(result4.truncationId).toBeDefined() }) it("should consider incoming content when deciding to truncate", async () => { @@ -510,14 +535,6 @@ describe("Context Management", () => { { ...messages[messages.length - 1], content: "" }, ] - // When truncating, always uses 0.5 fraction - // With 4 messages after the first, 0.5 fraction means remove 2 messages - const expectedResult = [ - messagesWithSmallContent[0], - messagesWithSmallContent[3], - messagesWithSmallContent[4], - ] - const result = await manageContext({ messages: messagesWithSmallContent, totalTokens, @@ -531,12 +548,15 @@ describe("Context Management", () => { profileThresholds: {}, currentProfileId: "default", }) - expect(result).toEqual({ - messages: expectedResult, - summary: "", - cost: 0, - prevContextTokens: totalTokens, - }) + + // Should have truncation + expect(result.truncationId).toBeDefined() + expect(result.messagesRemoved).toBe(2) // With 4 messages after first, 0.5 fraction = 2 to remove + expect(result.summary).toBe("") + expect(result.cost).toBe(0) + expect(result.prevContextTokens).toBe(totalTokens) + // Should have all original messages + truncation marker (non-destructive) + expect(result.messages.length).toBe(6) // 5 original + 1 marker }) it("should use summarizeConversation when autoCondenseContext is true and tokens exceed threshold", async () => { @@ -650,10 +670,13 @@ describe("Context Management", () => { // Verify summarizeConversation was called expect(summarizeSpy).toHaveBeenCalled() - // Verify it fell back to truncation - expect(result.messages).toEqual(expectedMessages) + // Verify it fell back to truncation (non-destructive) + expect(result.truncationId).toBeDefined() + expect(result.messagesRemoved).toBe(2) expect(result.summary).toBe("") expect(result.prevContextTokens).toBe(totalTokens) + // Should have all original messages + truncation marker + expect(result.messages.length).toBe(6) // 5 original + 1 marker // The cost might be different than expected, so we don't check it // Clean up @@ -697,13 +720,14 @@ describe("Context Management", () => { // Verify summarizeConversation was not called expect(summarizeSpy).not.toHaveBeenCalled() - // Verify it used truncation - expect(result).toEqual({ - messages: expectedMessages, - summary: "", - cost: 0, - prevContextTokens: totalTokens, - }) + // Verify it used truncation (non-destructive) + expect(result.truncationId).toBeDefined() + expect(result.messagesRemoved).toBe(2) + expect(result.summary).toBe("") + expect(result.cost).toBe(0) + expect(result.prevContextTokens).toBe(totalTokens) + // Should have all original messages + truncation marker + expect(result.messages.length).toBe(6) // 5 original + 1 marker // Clean up summarizeSpy.mockRestore() @@ -1093,7 +1117,10 @@ describe("Context Management", () => { currentProfileId: "default", }) expect(result2.messages).not.toEqual(messagesWithSmallContent) - expect(result2.messages.length).toBe(3) // Truncated with 0.5 fraction + // Should have all original messages + truncation marker (non-destructive) + expect(result2.messages.length).toBe(6) // 5 original + 1 marker + expect(result2.truncationId).toBeDefined() + expect(result2.messagesRemoved).toBe(2) expect(result2.summary).toBe("") expect(result2.cost).toBe(0) expect(result2.prevContextTokens).toBe(50001) @@ -1146,7 +1173,9 @@ describe("Context Management", () => { currentProfileId: "default", }) expect(result2.messages).not.toEqual(messagesWithSmallContent) - expect(result2.messages.length).toBe(3) // Truncated with 0.5 fraction + // Should have all original messages + truncation marker (non-destructive) + expect(result2.messages.length).toBe(6) // 5 original + 1 marker + expect(result2.truncationId).toBeDefined() expect(result2.summary).toBe("") expect(result2.cost).toBe(0) expect(result2.prevContextTokens).toBe(81809) @@ -1192,8 +1221,10 @@ describe("Context Management", () => { profileThresholds: {}, currentProfileId: "default", }) - expect(result2).not.toEqual(messagesWithSmallContent) - expect(result2.messages.length).toBe(3) // Truncated with 0.5 fraction + expect(result2.messages).not.toEqual(messagesWithSmallContent) + // Should have all original messages + truncation marker (non-destructive) + expect(result2.messages.length).toBe(6) // 5 original + 1 marker + expect(result2.truncationId).toBeDefined() }) it("should handle large context windows appropriately", async () => { @@ -1237,8 +1268,10 @@ describe("Context Management", () => { profileThresholds: {}, currentProfileId: "default", }) - expect(result2).not.toEqual(messagesWithSmallContent) - expect(result2.messages.length).toBe(3) // Truncated with 0.5 fraction + expect(result2.messages).not.toEqual(messagesWithSmallContent) + // Should have all original messages + truncation marker (non-destructive) + expect(result2.messages.length).toBe(6) // 5 original + 1 marker + expect(result2.truncationId).toBeDefined() }) }) }) diff --git a/src/core/context-management/__tests__/truncation.spec.ts b/src/core/context-management/__tests__/truncation.spec.ts new file mode 100644 index 00000000000..185a69ca7a0 --- /dev/null +++ b/src/core/context-management/__tests__/truncation.spec.ts @@ -0,0 +1,402 @@ +import { describe, it, expect, beforeEach } from "vitest" +import { TelemetryService } from "@roo-code/telemetry" +import { truncateConversation } from "../index" +import { getEffectiveApiHistory, cleanupAfterTruncation } from "../../condense" +import { ApiMessage } from "../../task-persistence/apiMessages" + +describe("Non-Destructive Sliding Window Truncation", () => { + let messages: ApiMessage[] + + beforeEach(() => { + // Initialize TelemetryService for tests + if (!TelemetryService.hasInstance()) { + TelemetryService.createInstance([]) + } + + // Create a sample conversation with 11 messages (1 initial + 10 conversation messages) + messages = [ + { role: "user", content: "Initial task", ts: 1000 }, + { role: "assistant", content: "Response 1", ts: 1100 }, + { role: "user", content: "Message 2", ts: 1200 }, + { role: "assistant", content: "Response 2", ts: 1300 }, + { role: "user", content: "Message 3", ts: 1400 }, + { role: "assistant", content: "Response 3", ts: 1500 }, + { role: "user", content: "Message 4", ts: 1600 }, + { role: "assistant", content: "Response 4", ts: 1700 }, + { role: "user", content: "Message 5", ts: 1800 }, + { role: "assistant", content: "Response 5", ts: 1900 }, + { role: "user", content: "Message 6", ts: 2000 }, + ] + }) + + describe("truncateConversation()", () => { + it("should tag messages with truncationParent instead of deleting", () => { + const result = truncateConversation(messages, 0.5, "test-task-id") + + // All messages should still be present + expect(result.messages.length).toBe(messages.length + 1) // +1 for truncation marker + + // Calculate expected messages to remove: floor((11-1) * 0.5) = 5, rounded to even = 4 + const expectedMessagesToRemove = 4 + + // Messages 1-4 should be tagged with truncationParent + for (let i = 1; i <= expectedMessagesToRemove; i++) { + // Account for truncation marker inserted at position 1 + const msgIndex = i < 1 ? i : i + 1 + expect(result.messages[msgIndex].truncationParent).toBeDefined() + expect(result.messages[msgIndex].truncationParent).toBe(result.truncationId) + } + + // First message should not be tagged + expect(result.messages[0].truncationParent).toBeUndefined() + + // Remaining messages should not be tagged + for (let i = expectedMessagesToRemove + 2; i < result.messages.length; i++) { + expect(result.messages[i].truncationParent).toBeUndefined() + } + }) + + it("should insert truncation marker with truncationId", () => { + const result = truncateConversation(messages, 0.5, "test-task-id") + + // Truncation marker should be at index 1 (after first message) + const marker = result.messages[1] + expect(marker.isTruncationMarker).toBe(true) + expect(marker.truncationId).toBeDefined() + expect(marker.truncationId).toBe(result.truncationId) + expect(marker.role).toBe("assistant") + expect(marker.content).toContain("Sliding window truncation") + }) + + it("should return truncationId and messagesRemoved", () => { + const result = truncateConversation(messages, 0.5, "test-task-id") + + expect(result.truncationId).toBeDefined() + expect(typeof result.truncationId).toBe("string") + expect(result.messagesRemoved).toBe(4) // floor((11-1) * 0.5) rounded to even + }) + + it("should round messagesToRemove to an even number", () => { + // Test with 12 messages (1 initial + 11 conversation) + const manyMessages: ApiMessage[] = [ + { role: "user", content: "Initial", ts: 1000 }, + ...Array.from({ length: 11 }, (_, i) => ({ + role: (i % 2 === 0 ? "assistant" : "user") as "assistant" | "user", + content: `Message ${i + 1}`, + ts: 1100 + i * 100, + })), + ] + + // fracToRemove=0.5 -> rawMessagesToRemove = floor(11 * 0.5) = 5 + // messagesToRemove = 5 - (5 % 2) = 4 (rounded down to even) + const result = truncateConversation(manyMessages, 0.5, "test-task-id") + expect(result.messagesRemoved).toBe(4) + }) + }) + + describe("getEffectiveApiHistory()", () => { + it("should filter out truncated messages when truncation marker exists", () => { + const truncationResult = truncateConversation(messages, 0.5, "test-task-id") + const effective = getEffectiveApiHistory(truncationResult.messages) + + // Should exclude 4 truncated messages but keep the first message and truncation marker + // Original: 11 messages + // After truncation: 11 + 1 marker = 12 + // Effective: 11 - 4 (hidden) + 1 (marker) = 8 + expect(effective.length).toBe(8) + + // First message should be present + expect(effective[0].content).toBe("Initial task") + + // Truncation marker should be present + expect(effective[1].isTruncationMarker).toBe(true) + + // Messages with truncationParent should be filtered out + for (const msg of effective) { + if (msg.truncationParent) { + throw new Error("Message with truncationParent should be filtered out") + } + } + }) + + it("should include truncated messages when truncation marker is removed", () => { + const truncationResult = truncateConversation(messages, 0.5, "test-task-id") + + // Remove the truncation marker (simulate rewind past truncation) + const messagesWithoutMarker = truncationResult.messages.filter((msg) => !msg.isTruncationMarker) + + const effective = getEffectiveApiHistory(messagesWithoutMarker) + + // All messages should be visible now + expect(effective.length).toBe(messages.length) + + // Verify first and last messages are present + expect(effective[0].content).toBe("Initial task") + expect(effective[effective.length - 1].content).toBe("Message 6") + }) + + it("should handle both condenseParent and truncationParent filtering", () => { + // Create a scenario with both condensing and truncation + const messagesWithCondense: ApiMessage[] = [ + { role: "user", content: "Initial", ts: 1000 }, + { role: "assistant", content: "Msg 1", ts: 1100, condenseParent: "condense-1" }, + { role: "user", content: "Msg 2", ts: 1200, condenseParent: "condense-1" }, + { + role: "assistant", + content: "Summary 1", + ts: 1250, + isSummary: true, + condenseId: "condense-1", + }, + { role: "user", content: "Msg 3", ts: 1300 }, + { role: "assistant", content: "Msg 4", ts: 1400 }, + ] + + const truncationResult = truncateConversation(messagesWithCondense, 0.5, "test-task-id") + const effective = getEffectiveApiHistory(truncationResult.messages) + + // Should filter both condensed messages and truncated messages + // Messages with condenseParent="condense-1" should be filtered (summary exists) + // Messages with truncationParent should be filtered (marker exists) + const hasCondensedMessage = effective.some((msg) => msg.condenseParent === "condense-1") + const hasTruncatedMessage = effective.some((msg) => msg.truncationParent) + + expect(hasCondensedMessage).toBe(false) + expect(hasTruncatedMessage).toBe(false) + }) + }) + + describe("cleanupAfterTruncation()", () => { + it("should clear orphaned truncationParent tags when marker is deleted", () => { + const truncationResult = truncateConversation(messages, 0.5, "test-task-id") + + // Remove the truncation marker (simulate rewind) + const messagesWithoutMarker = truncationResult.messages.filter((msg) => !msg.isTruncationMarker) + + const cleaned = cleanupAfterTruncation(messagesWithoutMarker) + + // All truncationParent tags should be cleared + for (const msg of cleaned) { + expect(msg.truncationParent).toBeUndefined() + } + }) + + it("should preserve truncationParent tags when marker still exists", () => { + const truncationResult = truncateConversation(messages, 0.5, "test-task-id") + + const cleaned = cleanupAfterTruncation(truncationResult.messages) + + // truncationParent tags should be preserved (marker still exists) + const taggedMessages = cleaned.filter((msg) => msg.truncationParent) + expect(taggedMessages.length).toBeGreaterThan(0) + + // All tagged messages should point to the existing marker + for (const msg of taggedMessages) { + expect(msg.truncationParent).toBe(truncationResult.truncationId) + } + }) + + it("should handle both condenseParent and truncationParent cleanup", () => { + const messagesWithBoth: ApiMessage[] = [ + { role: "user", content: "Initial", ts: 1000 }, + { role: "assistant", content: "Msg 1", ts: 1100, condenseParent: "orphan-condense" }, + { role: "user", content: "Msg 2", ts: 1200, truncationParent: "orphan-truncation" }, + { role: "assistant", content: "Msg 3", ts: 1300 }, + ] + + const cleaned = cleanupAfterTruncation(messagesWithBoth) + + // Both orphaned parent references should be cleared + expect(cleaned[1].condenseParent).toBeUndefined() + expect(cleaned[2].truncationParent).toBeUndefined() + }) + + it("should preserve valid parent references", () => { + const messagesWithValidParents: ApiMessage[] = [ + { role: "user", content: "Initial", ts: 1000 }, + { role: "assistant", content: "Msg 1", ts: 1100, condenseParent: "valid-condense" }, + { + role: "assistant", + content: "Summary", + ts: 1150, + isSummary: true, + condenseId: "valid-condense", + }, + { role: "user", content: "Msg 2", ts: 1200, truncationParent: "valid-truncation" }, + { + role: "assistant", + content: "Truncation marker", + ts: 1250, + isTruncationMarker: true, + truncationId: "valid-truncation", + }, + ] + + const cleaned = cleanupAfterTruncation(messagesWithValidParents) + + // Valid parent references should be preserved + expect(cleaned[1].condenseParent).toBe("valid-condense") + expect(cleaned[3].truncationParent).toBe("valid-truncation") + }) + }) + + describe("Rewind past truncation integration", () => { + it("should restore hidden messages when rewinding past truncation point", () => { + // Step 1: Perform truncation + const truncationResult = truncateConversation(messages, 0.5, "test-task-id") + + // Step 2: Verify messages are hidden initially + const effectiveBeforeRewind = getEffectiveApiHistory(truncationResult.messages) + expect(effectiveBeforeRewind.length).toBeLessThan(messages.length) + + // Step 3: Simulate rewind by removing truncation marker and subsequent messages + // In practice this would be done via removeMessagesThisAndSubsequent + const markerIndex = truncationResult.messages.findIndex((msg) => msg.isTruncationMarker) + const messagesAfterRewind = truncationResult.messages.slice(0, markerIndex) + + // Step 4: Clean up orphaned parent references + const cleanedAfterRewind = cleanupAfterTruncation(messagesAfterRewind) + + // Step 5: Get effective history after cleanup + const effectiveAfterRewind = getEffectiveApiHistory(cleanedAfterRewind) + + // All original messages before the marker should be restored + expect(effectiveAfterRewind.length).toBe(markerIndex) + + // No messages should have truncationParent + for (const msg of effectiveAfterRewind) { + expect(msg.truncationParent).toBeUndefined() + } + }) + + it("should handle multiple truncations correctly", () => { + // Step 1: First truncation + const firstTruncation = truncateConversation(messages, 0.5, "task-1") + + // Step 2: Get effective history and simulate more messages being added + const effectiveAfterFirst = getEffectiveApiHistory(firstTruncation.messages) + const moreMessages: ApiMessage[] = [ + ...firstTruncation.messages, + { role: "user", content: "New message 1", ts: 3000 }, + { role: "assistant", content: "New response 1", ts: 3100 }, + { role: "user", content: "New message 2", ts: 3200 }, + { role: "assistant", content: "New response 2", ts: 3300 }, + ] + + // Step 3: Second truncation + const secondTruncation = truncateConversation(moreMessages, 0.5, "task-1") + + // Step 4: Get effective history after second truncation + const effectiveAfterSecond = getEffectiveApiHistory(secondTruncation.messages) + + // Should have messages hidden by both truncations filtered out + const firstMarker = secondTruncation.messages.find( + (msg) => msg.isTruncationMarker && msg.truncationId === firstTruncation.truncationId, + ) + const secondMarker = secondTruncation.messages.find( + (msg) => msg.isTruncationMarker && msg.truncationId === secondTruncation.truncationId, + ) + + expect(firstMarker).toBeDefined() + expect(secondMarker).toBeDefined() + + // Messages tagged with either truncationId should be filtered + for (const msg of effectiveAfterSecond) { + if (msg.truncationParent === firstTruncation.truncationId) { + throw new Error("First truncation messages should be filtered") + } + if (msg.truncationParent === secondTruncation.truncationId) { + throw new Error("Second truncation messages should be filtered") + } + } + }) + + it("should handle rewinding when second truncation affects first truncation marker", () => { + // Step 1: First truncation + const firstTruncation = truncateConversation(messages, 0.5, "task-1") + + // Step 2: Add more messages AFTER getting effective history + // This simulates real usage where we only send effective messages to API + const effectiveAfterFirst = getEffectiveApiHistory(firstTruncation.messages) + const moreMessages: ApiMessage[] = [ + ...firstTruncation.messages, // Keep full history with tagged messages + { role: "user", content: "New message 1", ts: 3000 }, + { role: "assistant", content: "New response 1", ts: 3100 }, + { role: "user", content: "New message 2", ts: 3200 }, + { role: "assistant", content: "New response 2", ts: 3300 }, + ] + + // Step 3: Second truncation - this will tag some messages including possibly the first marker + const secondTruncation = truncateConversation(moreMessages, 0.5, "task-1") + + // Step 4: Simulate rewind past second truncation marker + const secondMarkerIndex = secondTruncation.messages.findIndex( + (msg) => msg.isTruncationMarker && msg.truncationId === secondTruncation.truncationId, + ) + const afterSecondRewind = secondTruncation.messages.slice(0, secondMarkerIndex) + + // Step 5: Clean up orphaned references + const cleaned = cleanupAfterTruncation(afterSecondRewind) + + // Step 6: Get effective history + const effective = getEffectiveApiHistory(cleaned) + + // The second truncation marker should be removed + const hasSecondTruncationMarker = effective.some( + (msg) => msg.isTruncationMarker && msg.truncationId === secondTruncation.truncationId, + ) + expect(hasSecondTruncationMarker).toBe(false) + + // Messages that were tagged by the second truncation should have those tags cleared + const hasSecondTruncationParent = cleaned.some( + (msg) => msg.truncationParent === secondTruncation.truncationId, + ) + expect(hasSecondTruncationParent).toBe(false) + + // First truncation marker and its tagged messages may or may not be present + // depending on whether the second truncation affected them + // The important thing is that cleanup works correctly + expect(cleaned.length).toBeGreaterThan(0) + }) + }) + + describe("Edge cases", () => { + it("should handle truncateConversation with fracToRemove=0", () => { + const result = truncateConversation(messages, 0, "test-task-id") + + // No messages should be tagged (messagesToRemove = 0) + const taggedMessages = result.messages.filter((msg) => msg.truncationParent) + expect(taggedMessages.length).toBe(0) + + // Should still have truncation marker + const marker = result.messages.find((msg) => msg.isTruncationMarker) + expect(marker).toBeDefined() + }) + + it("should handle truncateConversation with very few messages", () => { + const fewMessages: ApiMessage[] = [ + { role: "user", content: "Initial", ts: 1000 }, + { role: "assistant", content: "Response", ts: 1100 }, + ] + + const result = truncateConversation(fewMessages, 0.5, "test-task-id") + + // Should not crash and should still create marker + expect(result.messages.length).toBeGreaterThan(0) + const marker = result.messages.find((msg) => msg.isTruncationMarker) + expect(marker).toBeDefined() + }) + + it("should handle empty condenseParent and truncationParent gracefully", () => { + const messagesWithoutTags: ApiMessage[] = [ + { role: "user", content: "Message 1", ts: 1000 }, + { role: "assistant", content: "Response 1", ts: 1100 }, + ] + + const cleaned = cleanupAfterTruncation(messagesWithoutTags) + + // Should return same messages unchanged + expect(cleaned).toEqual(messagesWithoutTags) + }) + }) +}) diff --git a/src/core/context-management/index.ts b/src/core/context-management/index.ts index 40ad688ae9a..54d2ff09c93 100644 --- a/src/core/context-management/index.ts +++ b/src/core/context-management/index.ts @@ -1,4 +1,5 @@ import { Anthropic } from "@anthropic-ai/sdk" +import crypto from "crypto" import { TelemetryService } from "@roo-code/telemetry" @@ -39,27 +40,62 @@ export async function estimateTokenCount( } /** - * Truncates a conversation by removing a fraction of the messages. + * Result of truncation operation, includes the truncation ID for UI events. + */ +export type TruncationResult = { + messages: ApiMessage[] + truncationId: string + messagesRemoved: number +} + +/** + * Truncates a conversation by tagging messages as hidden instead of removing them. * * The first message is always retained, and a specified fraction (rounded to an even number) - * of messages from the beginning (excluding the first) is removed. + * of messages from the beginning (excluding the first) is tagged with truncationParent. + * A truncation marker is inserted to track where truncation occurred. * - * This implements the sliding window truncation behavior. + * This implements non-destructive sliding window truncation, allowing messages to be + * restored if the user rewinds past the truncation point. * * @param {ApiMessage[]} messages - The conversation messages. - * @param {number} fracToRemove - The fraction (between 0 and 1) of messages (excluding the first) to remove. + * @param {number} fracToRemove - The fraction (between 0 and 1) of messages (excluding the first) to hide. * @param {string} taskId - The task ID for the conversation, used for telemetry - * @returns {ApiMessage[]} The truncated conversation messages. + * @returns {TruncationResult} Object containing the tagged messages, truncation ID, and count of messages removed. */ -export function truncateConversation(messages: ApiMessage[], fracToRemove: number, taskId: string): ApiMessage[] { +export function truncateConversation(messages: ApiMessage[], fracToRemove: number, taskId: string): TruncationResult { TelemetryService.instance.captureSlidingWindowTruncation(taskId) - const truncatedMessages = [messages[0]] + + const truncationId = crypto.randomUUID() const rawMessagesToRemove = Math.floor((messages.length - 1) * fracToRemove) const messagesToRemove = rawMessagesToRemove - (rawMessagesToRemove % 2) - const remainingMessages = messages.slice(messagesToRemove + 1) - truncatedMessages.push(...remainingMessages) - return truncatedMessages + // Tag messages that are being "truncated" (hidden from API calls) + const taggedMessages = messages.map((msg, index) => { + if (index > 0 && index <= messagesToRemove) { + return { ...msg, truncationParent: truncationId } + } + return msg + }) + + // Insert truncation marker after first message (so we know a truncation happened) + const firstKeptTs = messages[messagesToRemove + 1]?.ts ?? Date.now() + const truncationMarker: ApiMessage = { + role: "assistant", + content: `[Sliding window truncation: ${messagesToRemove} messages hidden to reduce context]`, + ts: firstKeptTs - 1, + isTruncationMarker: true, + truncationId, + } + + // Insert marker after first message + const result = [taggedMessages[0], truncationMarker, ...taggedMessages.slice(1)] + + return { + messages: result, + truncationId, + messagesRemoved: messagesToRemove, + } } /** @@ -89,7 +125,11 @@ export type ContextManagementOptions = { useNativeTools?: boolean } -export type ContextManagementResult = SummarizeResponse & { prevContextTokens: number } +export type ContextManagementResult = SummarizeResponse & { + prevContextTokens: number + truncationId?: string + messagesRemoved?: number +} /** * Conditionally manages conversation context (condense and fallback truncation). @@ -178,8 +218,16 @@ export async function manageContext({ // Fall back to sliding window truncation if needed if (prevContextTokens > allowedTokens) { - const truncatedMessages = truncateConversation(messages, 0.5, taskId) - return { messages: truncatedMessages, prevContextTokens, summary: "", cost, error } + const truncationResult = truncateConversation(messages, 0.5, taskId) + return { + messages: truncationResult.messages, + prevContextTokens, + summary: "", + cost, + error, + truncationId: truncationResult.truncationId, + messagesRemoved: truncationResult.messagesRemoved, + } } // No truncation or condensation needed return { messages, summary: "", cost, prevContextTokens, error } diff --git a/src/core/diff/insert-groups.ts b/src/core/diff/insert-groups.ts deleted file mode 100644 index 5bd7238b063..00000000000 --- a/src/core/diff/insert-groups.ts +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Inserts multiple groups of elements at specified indices in an array - * @param original Array to insert into, split by lines - * @param insertGroups Array of groups to insert, each with an index and elements to insert. - * If index is -1, the elements will be appended to the end of the array. - * @returns New array with all insertions applied - */ -export interface InsertGroup { - index: number - elements: string[] -} - -export function insertGroups(original: string[], insertGroups: InsertGroup[]): string[] { - // Handle groups with index -1 separately and sort remaining groups by index - const appendGroups = insertGroups.filter((group) => group.index === -1) - const normalGroups = insertGroups.filter((group) => group.index !== -1).sort((a, b) => a.index - b.index) - - let result: string[] = [] - let lastIndex = 0 - - normalGroups.forEach(({ index, elements }) => { - // Add elements from original array up to insertion point - result.push(...original.slice(lastIndex, index)) - // Add the group of elements - result.push(...elements) - lastIndex = index - }) - - // Add remaining elements from original array - result.push(...original.slice(lastIndex)) - - // Append elements from groups with index -1 at the end - appendGroups.forEach(({ elements }) => { - result.push(...elements) - }) - - return result -} diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/architect-mode-prompt.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/architect-mode-prompt.snap index a458972a3e5..ff2d3ec4b62 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/architect-mode-prompt.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/architect-mode-prompt.snap @@ -193,36 +193,6 @@ Example: Requesting to write to frontend-config.json -## insert_content -Description: Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace directory /test/path -- line: (required) Line number where content will be inserted (1-based) - Use 0 to append at end of file - Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: - -src/utils.ts -1 - -// Add imports at start of file -import { sum } from './math'; - - - -Example for appending to the end of file: - -src/utils.ts -0 - -// This is the end of the file - - - - ## ask_followup_question Description: Ask the user a question to gather additional information needed to complete the task. Use when you need clarification or more details to proceed effectively. @@ -406,7 +376,7 @@ CAPABILITIES - When the user initially gives you a task, a recursive list of all filepaths in the current workspace directory ('/test/path') will be included in environment_details. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further. If you need to further explore directories such as outside the current workspace directory, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure, like the Desktop. - You can use search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring. - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task. - - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file or insert_content tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. + - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance. ==== @@ -427,9 +397,7 @@ RULES - When using the search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use read_file to examine the full context of interesting matches before using write_to_file to make informed changes. - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser. -- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites), insert_content (for adding lines to files). -- The insert_content tool adds lines of text to files at a specific line number, such as adding a new function to a JavaScript file or inserting a new route in a Python file. Use line number 0 to append at the end of the file, or any positive number to insert before that line. -- You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files. +- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites). - When using the write_to_file tool to modify a file, use the tool directly with the desired content. You do not need to display the content before using the tool. ALWAYS provide the COMPLETE file content in your response. This is NON-NEGOTIABLE. Partial updates or placeholders like '// rest of code unchanged' are STRICTLY FORBIDDEN. You MUST include ALL parts of the file, even if they haven't been modified. Failure to do so will result in incomplete or broken code, severely impacting the user's project. - Some modes have restrictions on which files they can edit. If you attempt to edit a restricted file, the operation will be rejected with a FileRestrictionError that will specify which file patterns are allowed for the current mode. - Be sure to consider the type of project (e.g. Python, JavaScript, web application) when determining the appropriate structure and files to include. Also consider what files may be most relevant to accomplishing the task, for example looking at a project's manifest file would help you understand the project's dependencies, which you could incorporate into any code you write. diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-disabled.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-disabled.snap index 4e38bce395b..6cae9e86ac4 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-disabled.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-disabled.snap @@ -192,36 +192,6 @@ Example: Requesting to write to frontend-config.json -## insert_content -Description: Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace directory /test/path -- line: (required) Line number where content will be inserted (1-based) - Use 0 to append at end of file - Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: - -src/utils.ts -1 - -// Add imports at start of file -import { sum } from './math'; - - - -Example for appending to the end of file: - -src/utils.ts -0 - -// This is the end of the file - - - - ## execute_command Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Prefer relative commands and paths that avoid location sensitivity for terminal consistency, e.g: `touch ./testdata/example.file`, `dir ./examples/model1/data/yaml`, or `go test ./cmd/front --config ./cmd/front/config.yml`. If directed by the user, you may open a terminal in a different directory by using the `cwd` parameter. Parameters: @@ -427,7 +397,7 @@ CAPABILITIES - When the user initially gives you a task, a recursive list of all filepaths in the current workspace directory ('/test/path') will be included in environment_details. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further. If you need to further explore directories such as outside the current workspace directory, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure, like the Desktop. - You can use search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring. - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task. - - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file or insert_content tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. + - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance. ==== @@ -448,9 +418,7 @@ RULES - When using the search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use read_file to examine the full context of interesting matches before using write_to_file to make informed changes. - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser. -- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites), insert_content (for adding lines to files). -- The insert_content tool adds lines of text to files at a specific line number, such as adding a new function to a JavaScript file or inserting a new route in a Python file. Use line number 0 to append at the end of the file, or any positive number to insert before that line. -- You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files. +- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites). - When using the write_to_file tool to modify a file, use the tool directly with the desired content. You do not need to display the content before using the tool. ALWAYS provide the COMPLETE file content in your response. This is NON-NEGOTIABLE. Partial updates or placeholders like '// rest of code unchanged' are STRICTLY FORBIDDEN. You MUST include ALL parts of the file, even if they haven't been modified. Failure to do so will result in incomplete or broken code, severely impacting the user's project. - Some modes have restrictions on which files they can edit. If you attempt to edit a restricted file, the operation will be rejected with a FileRestrictionError that will specify which file patterns are allowed for the current mode. - Be sure to consider the type of project (e.g. Python, JavaScript, web application) when determining the appropriate structure and files to include. Also consider what files may be most relevant to accomplishing the task, for example looking at a project's manifest file would help you understand the project's dependencies, which you could incorporate into any code you write. diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap index ba309a06a59..63fa6e7897b 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap @@ -193,36 +193,6 @@ Example: Requesting to write to frontend-config.json -## insert_content -Description: Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace directory /test/path -- line: (required) Line number where content will be inserted (1-based) - Use 0 to append at end of file - Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: - -src/utils.ts -1 - -// Add imports at start of file -import { sum } from './math'; - - - -Example for appending to the end of file: - -src/utils.ts -0 - -// This is the end of the file - - - - ## execute_command Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Prefer relative commands and paths that avoid location sensitivity for terminal consistency, e.g: `touch ./testdata/example.file`, `dir ./examples/model1/data/yaml`, or `go test ./cmd/front --config ./cmd/front/config.yml`. If directed by the user, you may open a terminal in a different directory by using the `cwd` parameter. Parameters: @@ -494,7 +464,7 @@ CAPABILITIES - When the user initially gives you a task, a recursive list of all filepaths in the current workspace directory ('/test/path') will be included in environment_details. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further. If you need to further explore directories such as outside the current workspace directory, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure, like the Desktop. - You can use search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring. - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task. - - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file or insert_content tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. + - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance. - You have access to MCP servers that may provide additional tools and resources. Each server may provide different capabilities that you can use to accomplish tasks more effectively. @@ -517,9 +487,7 @@ RULES - When using the search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use read_file to examine the full context of interesting matches before using write_to_file to make informed changes. - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser. -- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites), insert_content (for adding lines to files). -- The insert_content tool adds lines of text to files at a specific line number, such as adding a new function to a JavaScript file or inserting a new route in a Python file. Use line number 0 to append at the end of the file, or any positive number to insert before that line. -- You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files. +- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites). - When using the write_to_file tool to modify a file, use the tool directly with the desired content. You do not need to display the content before using the tool. ALWAYS provide the COMPLETE file content in your response. This is NON-NEGOTIABLE. Partial updates or placeholders like '// rest of code unchanged' are STRICTLY FORBIDDEN. You MUST include ALL parts of the file, even if they haven't been modified. Failure to do so will result in incomplete or broken code, severely impacting the user's project. - Some modes have restrictions on which files they can edit. If you attempt to edit a restricted file, the operation will be rejected with a FileRestrictionError that will specify which file patterns are allowed for the current mode. - Be sure to consider the type of project (e.g. Python, JavaScript, web application) when determining the appropriate structure and files to include. Also consider what files may be most relevant to accomplishing the task, for example looking at a project's manifest file would help you understand the project's dependencies, which you could incorporate into any code you write. diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/partial-reads-enabled.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/partial-reads-enabled.snap index ba7207d7364..4ef4285d5ad 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/partial-reads-enabled.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/partial-reads-enabled.snap @@ -198,36 +198,6 @@ Example: Requesting to write to frontend-config.json -## insert_content -Description: Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace directory /test/path -- line: (required) Line number where content will be inserted (1-based) - Use 0 to append at end of file - Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: - -src/utils.ts -1 - -// Add imports at start of file -import { sum } from './math'; - - - -Example for appending to the end of file: - -src/utils.ts -0 - -// This is the end of the file - - - - ## execute_command Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Prefer relative commands and paths that avoid location sensitivity for terminal consistency, e.g: `touch ./testdata/example.file`, `dir ./examples/model1/data/yaml`, or `go test ./cmd/front --config ./cmd/front/config.yml`. If directed by the user, you may open a terminal in a different directory by using the `cwd` parameter. Parameters: @@ -433,7 +403,7 @@ CAPABILITIES - When the user initially gives you a task, a recursive list of all filepaths in the current workspace directory ('/test/path') will be included in environment_details. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further. If you need to further explore directories such as outside the current workspace directory, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure, like the Desktop. - You can use search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring. - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task. - - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file or insert_content tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. + - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance. ==== @@ -454,9 +424,7 @@ RULES - When using the search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use read_file to examine the full context of interesting matches before using write_to_file to make informed changes. - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser. -- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites), insert_content (for adding lines to files). -- The insert_content tool adds lines of text to files at a specific line number, such as adding a new function to a JavaScript file or inserting a new route in a Python file. Use line number 0 to append at the end of the file, or any positive number to insert before that line. -- You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files. +- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites). - When using the write_to_file tool to modify a file, use the tool directly with the desired content. You do not need to display the content before using the tool. ALWAYS provide the COMPLETE file content in your response. This is NON-NEGOTIABLE. Partial updates or placeholders like '// rest of code unchanged' are STRICTLY FORBIDDEN. You MUST include ALL parts of the file, even if they haven't been modified. Failure to do so will result in incomplete or broken code, severely impacting the user's project. - Some modes have restrictions on which files they can edit. If you attempt to edit a restricted file, the operation will be rejected with a FileRestrictionError that will specify which file patterns are allowed for the current mode. - Be sure to consider the type of project (e.g. Python, JavaScript, web application) when determining the appropriate structure and files to include. Also consider what files may be most relevant to accomplishing the task, for example looking at a project's manifest file would help you understand the project's dependencies, which you could incorporate into any code you write. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/consistent-system-prompt.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/consistent-system-prompt.snap index f8392d15496..6a90ff68b0e 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/consistent-system-prompt.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/consistent-system-prompt.snap @@ -193,36 +193,6 @@ Example: Requesting to write to frontend-config.json -## insert_content -Description: Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace directory /test/path -- line: (required) Line number where content will be inserted (1-based) - Use 0 to append at end of file - Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: - -src/utils.ts -1 - -// Add imports at start of file -import { sum } from './math'; - - - -Example for appending to the end of file: - -src/utils.ts -0 - -// This is the end of the file - - - - ## execute_command Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Prefer relative commands and paths that avoid location sensitivity for terminal consistency, e.g: `touch ./testdata/example.file`, `dir ./examples/model1/data/yaml`, or `go test ./cmd/front --config ./cmd/front/config.yml`. If directed by the user, you may open a terminal in a different directory by using the `cwd` parameter. Parameters: @@ -428,7 +398,7 @@ CAPABILITIES - When the user initially gives you a task, a recursive list of all filepaths in the current workspace directory ('/test/path') will be included in environment_details. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further. If you need to further explore directories such as outside the current workspace directory, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure, like the Desktop. - You can use search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring. - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task. - - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file or insert_content tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. + - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance. ==== @@ -449,9 +419,7 @@ RULES - When using the search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use read_file to examine the full context of interesting matches before using write_to_file to make informed changes. - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser. -- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites), insert_content (for adding lines to files). -- The insert_content tool adds lines of text to files at a specific line number, such as adding a new function to a JavaScript file or inserting a new route in a Python file. Use line number 0 to append at the end of the file, or any positive number to insert before that line. -- You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files. +- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites). - When using the write_to_file tool to modify a file, use the tool directly with the desired content. You do not need to display the content before using the tool. ALWAYS provide the COMPLETE file content in your response. This is NON-NEGOTIABLE. Partial updates or placeholders like '// rest of code unchanged' are STRICTLY FORBIDDEN. You MUST include ALL parts of the file, even if they haven't been modified. Failure to do so will result in incomplete or broken code, severely impacting the user's project. - Some modes have restrictions on which files they can edit. If you attempt to edit a restricted file, the operation will be rejected with a FileRestrictionError that will specify which file patterns are allowed for the current mode. - Be sure to consider the type of project (e.g. Python, JavaScript, web application) when determining the appropriate structure and files to include. Also consider what files may be most relevant to accomplishing the task, for example looking at a project's manifest file would help you understand the project's dependencies, which you could incorporate into any code you write. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-computer-use-support.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-computer-use-support.snap index 03efe8df408..9553257b852 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-computer-use-support.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-computer-use-support.snap @@ -193,36 +193,6 @@ Example: Requesting to write to frontend-config.json -## insert_content -Description: Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace directory /test/path -- line: (required) Line number where content will be inserted (1-based) - Use 0 to append at end of file - Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: - -src/utils.ts -1 - -// Add imports at start of file -import { sum } from './math'; - - - -Example for appending to the end of file: - -src/utils.ts -0 - -// This is the end of the file - - - - ## browser_action Description: Request to interact with a Puppeteer-controlled browser. Every action, except `close`, will be responded to with a screenshot of the browser's current state, along with any new console logs. You may only perform one browser action per message, and wait for the user's response including a screenshot and logs to determine the next action. @@ -496,7 +466,7 @@ CAPABILITIES - When the user initially gives you a task, a recursive list of all filepaths in the current workspace directory ('/test/path') will be included in environment_details. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further. If you need to further explore directories such as outside the current workspace directory, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure, like the Desktop. - You can use search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring. - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task. - - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file or insert_content tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. + - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance. - You can use the browser_action tool to interact with websites (including html files and locally running development servers) through a Puppeteer-controlled browser when you feel it is necessary in accomplishing the user's task. This tool is particularly useful for web development tasks as it allows you to launch a browser, navigate to pages, interact with elements through clicks and keyboard input, and capture the results through screenshots and console logs. This tool may be useful at key stages of web development tasks-such as after implementing new features, making substantial changes, when troubleshooting issues, or to verify the result of your work. You can analyze the provided screenshots to ensure correct rendering or identify errors, and review console logs for runtime issues. - For example, if asked to add a component to a react website, you might create the necessary files, use execute_command to run the site locally, then use browser_action to launch the browser, navigate to the local server, and verify the component renders & functions correctly before closing the browser. @@ -519,9 +489,7 @@ RULES - When using the search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use read_file to examine the full context of interesting matches before using write_to_file to make informed changes. - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser. -- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites), insert_content (for adding lines to files). -- The insert_content tool adds lines of text to files at a specific line number, such as adding a new function to a JavaScript file or inserting a new route in a Python file. Use line number 0 to append at the end of the file, or any positive number to insert before that line. -- You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files. +- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites). - When using the write_to_file tool to modify a file, use the tool directly with the desired content. You do not need to display the content before using the tool. ALWAYS provide the COMPLETE file content in your response. This is NON-NEGOTIABLE. Partial updates or placeholders like '// rest of code unchanged' are STRICTLY FORBIDDEN. You MUST include ALL parts of the file, even if they haven't been modified. Failure to do so will result in incomplete or broken code, severely impacting the user's project. - Some modes have restrictions on which files they can edit. If you attempt to edit a restricted file, the operation will be rejected with a FileRestrictionError that will specify which file patterns are allowed for the current mode. - Be sure to consider the type of project (e.g. Python, JavaScript, web application) when determining the appropriate structure and files to include. Also consider what files may be most relevant to accomplishing the task, for example looking at a project's manifest file would help you understand the project's dependencies, which you could incorporate into any code you write. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-false.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-false.snap index f8392d15496..6a90ff68b0e 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-false.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-false.snap @@ -193,36 +193,6 @@ Example: Requesting to write to frontend-config.json -## insert_content -Description: Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace directory /test/path -- line: (required) Line number where content will be inserted (1-based) - Use 0 to append at end of file - Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: - -src/utils.ts -1 - -// Add imports at start of file -import { sum } from './math'; - - - -Example for appending to the end of file: - -src/utils.ts -0 - -// This is the end of the file - - - - ## execute_command Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Prefer relative commands and paths that avoid location sensitivity for terminal consistency, e.g: `touch ./testdata/example.file`, `dir ./examples/model1/data/yaml`, or `go test ./cmd/front --config ./cmd/front/config.yml`. If directed by the user, you may open a terminal in a different directory by using the `cwd` parameter. Parameters: @@ -428,7 +398,7 @@ CAPABILITIES - When the user initially gives you a task, a recursive list of all filepaths in the current workspace directory ('/test/path') will be included in environment_details. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further. If you need to further explore directories such as outside the current workspace directory, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure, like the Desktop. - You can use search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring. - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task. - - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file or insert_content tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. + - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance. ==== @@ -449,9 +419,7 @@ RULES - When using the search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use read_file to examine the full context of interesting matches before using write_to_file to make informed changes. - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser. -- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites), insert_content (for adding lines to files). -- The insert_content tool adds lines of text to files at a specific line number, such as adding a new function to a JavaScript file or inserting a new route in a Python file. Use line number 0 to append at the end of the file, or any positive number to insert before that line. -- You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files. +- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites). - When using the write_to_file tool to modify a file, use the tool directly with the desired content. You do not need to display the content before using the tool. ALWAYS provide the COMPLETE file content in your response. This is NON-NEGOTIABLE. Partial updates or placeholders like '// rest of code unchanged' are STRICTLY FORBIDDEN. You MUST include ALL parts of the file, even if they haven't been modified. Failure to do so will result in incomplete or broken code, severely impacting the user's project. - Some modes have restrictions on which files they can edit. If you attempt to edit a restricted file, the operation will be rejected with a FileRestrictionError that will specify which file patterns are allowed for the current mode. - Be sure to consider the type of project (e.g. Python, JavaScript, web application) when determining the appropriate structure and files to include. Also consider what files may be most relevant to accomplishing the task, for example looking at a project's manifest file would help you understand the project's dependencies, which you could incorporate into any code you write. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-true.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-true.snap index 7629d56c9be..89f187cea9b 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-true.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-true.snap @@ -281,36 +281,6 @@ Example: Requesting to write to frontend-config.json -## insert_content -Description: Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace directory /test/path -- line: (required) Line number where content will be inserted (1-based) - Use 0 to append at end of file - Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: - -src/utils.ts -1 - -// Add imports at start of file -import { sum } from './math'; - - - -Example for appending to the end of file: - -src/utils.ts -0 - -// This is the end of the file - - - - ## execute_command Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Prefer relative commands and paths that avoid location sensitivity for terminal consistency, e.g: `touch ./testdata/example.file`, `dir ./examples/model1/data/yaml`, or `go test ./cmd/front --config ./cmd/front/config.yml`. If directed by the user, you may open a terminal in a different directory by using the `cwd` parameter. Parameters: @@ -516,7 +486,7 @@ CAPABILITIES - When the user initially gives you a task, a recursive list of all filepaths in the current workspace directory ('/test/path') will be included in environment_details. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further. If you need to further explore directories such as outside the current workspace directory, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure, like the Desktop. - You can use search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring. - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task. - - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the apply_diff, write_to_file, or insert_content tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. + - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the apply_diff or write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance. ==== @@ -537,8 +507,7 @@ RULES - When using the search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use read_file to examine the full context of interesting matches before using apply_diff or write_to_file to make informed changes. - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser. -- For editing files, you have access to these tools: apply_diff (for surgical edits - targeted changes to specific lines or functions), write_to_file (for creating new files or complete file rewrites), insert_content (for adding lines to files). -- The insert_content tool adds lines of text to files at a specific line number, such as adding a new function to a JavaScript file or inserting a new route in a Python file. Use line number 0 to append at the end of the file, or any positive number to insert before that line. +- For editing files, you have access to these tools: apply_diff (for surgical edits - targeted changes to specific lines or functions), write_to_file (for creating new files or complete file rewrites). - You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files. - When using the write_to_file tool to modify a file, use the tool directly with the desired content. You do not need to display the content before using the tool. ALWAYS provide the COMPLETE file content in your response. This is NON-NEGOTIABLE. Partial updates or placeholders like '// rest of code unchanged' are STRICTLY FORBIDDEN. You MUST include ALL parts of the file, even if they haven't been modified. Failure to do so will result in incomplete or broken code, severely impacting the user's project. - Some modes have restrictions on which files they can edit. If you attempt to edit a restricted file, the operation will be rejected with a FileRestrictionError that will specify which file patterns are allowed for the current mode. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-undefined.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-undefined.snap index f8392d15496..6a90ff68b0e 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-undefined.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-undefined.snap @@ -193,36 +193,6 @@ Example: Requesting to write to frontend-config.json -## insert_content -Description: Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace directory /test/path -- line: (required) Line number where content will be inserted (1-based) - Use 0 to append at end of file - Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: - -src/utils.ts -1 - -// Add imports at start of file -import { sum } from './math'; - - - -Example for appending to the end of file: - -src/utils.ts -0 - -// This is the end of the file - - - - ## execute_command Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Prefer relative commands and paths that avoid location sensitivity for terminal consistency, e.g: `touch ./testdata/example.file`, `dir ./examples/model1/data/yaml`, or `go test ./cmd/front --config ./cmd/front/config.yml`. If directed by the user, you may open a terminal in a different directory by using the `cwd` parameter. Parameters: @@ -428,7 +398,7 @@ CAPABILITIES - When the user initially gives you a task, a recursive list of all filepaths in the current workspace directory ('/test/path') will be included in environment_details. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further. If you need to further explore directories such as outside the current workspace directory, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure, like the Desktop. - You can use search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring. - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task. - - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file or insert_content tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. + - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance. ==== @@ -449,9 +419,7 @@ RULES - When using the search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use read_file to examine the full context of interesting matches before using write_to_file to make informed changes. - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser. -- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites), insert_content (for adding lines to files). -- The insert_content tool adds lines of text to files at a specific line number, such as adding a new function to a JavaScript file or inserting a new route in a Python file. Use line number 0 to append at the end of the file, or any positive number to insert before that line. -- You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files. +- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites). - When using the write_to_file tool to modify a file, use the tool directly with the desired content. You do not need to display the content before using the tool. ALWAYS provide the COMPLETE file content in your response. This is NON-NEGOTIABLE. Partial updates or placeholders like '// rest of code unchanged' are STRICTLY FORBIDDEN. You MUST include ALL parts of the file, even if they haven't been modified. Failure to do so will result in incomplete or broken code, severely impacting the user's project. - Some modes have restrictions on which files they can edit. If you attempt to edit a restricted file, the operation will be rejected with a FileRestrictionError that will specify which file patterns are allowed for the current mode. - Be sure to consider the type of project (e.g. Python, JavaScript, web application) when determining the appropriate structure and files to include. Also consider what files may be most relevant to accomplishing the task, for example looking at a project's manifest file would help you understand the project's dependencies, which you could incorporate into any code you write. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-different-viewport-size.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-different-viewport-size.snap index f8392d15496..6a90ff68b0e 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-different-viewport-size.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-different-viewport-size.snap @@ -193,36 +193,6 @@ Example: Requesting to write to frontend-config.json -## insert_content -Description: Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace directory /test/path -- line: (required) Line number where content will be inserted (1-based) - Use 0 to append at end of file - Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: - -src/utils.ts -1 - -// Add imports at start of file -import { sum } from './math'; - - - -Example for appending to the end of file: - -src/utils.ts -0 - -// This is the end of the file - - - - ## execute_command Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Prefer relative commands and paths that avoid location sensitivity for terminal consistency, e.g: `touch ./testdata/example.file`, `dir ./examples/model1/data/yaml`, or `go test ./cmd/front --config ./cmd/front/config.yml`. If directed by the user, you may open a terminal in a different directory by using the `cwd` parameter. Parameters: @@ -428,7 +398,7 @@ CAPABILITIES - When the user initially gives you a task, a recursive list of all filepaths in the current workspace directory ('/test/path') will be included in environment_details. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further. If you need to further explore directories such as outside the current workspace directory, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure, like the Desktop. - You can use search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring. - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task. - - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file or insert_content tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. + - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance. ==== @@ -449,9 +419,7 @@ RULES - When using the search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use read_file to examine the full context of interesting matches before using write_to_file to make informed changes. - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser. -- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites), insert_content (for adding lines to files). -- The insert_content tool adds lines of text to files at a specific line number, such as adding a new function to a JavaScript file or inserting a new route in a Python file. Use line number 0 to append at the end of the file, or any positive number to insert before that line. -- You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files. +- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites). - When using the write_to_file tool to modify a file, use the tool directly with the desired content. You do not need to display the content before using the tool. ALWAYS provide the COMPLETE file content in your response. This is NON-NEGOTIABLE. Partial updates or placeholders like '// rest of code unchanged' are STRICTLY FORBIDDEN. You MUST include ALL parts of the file, even if they haven't been modified. Failure to do so will result in incomplete or broken code, severely impacting the user's project. - Some modes have restrictions on which files they can edit. If you attempt to edit a restricted file, the operation will be rejected with a FileRestrictionError that will specify which file patterns are allowed for the current mode. - Be sure to consider the type of project (e.g. Python, JavaScript, web application) when determining the appropriate structure and files to include. Also consider what files may be most relevant to accomplishing the task, for example looking at a project's manifest file would help you understand the project's dependencies, which you could incorporate into any code you write. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap index ba309a06a59..63fa6e7897b 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap @@ -193,36 +193,6 @@ Example: Requesting to write to frontend-config.json -## insert_content -Description: Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace directory /test/path -- line: (required) Line number where content will be inserted (1-based) - Use 0 to append at end of file - Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: - -src/utils.ts -1 - -// Add imports at start of file -import { sum } from './math'; - - - -Example for appending to the end of file: - -src/utils.ts -0 - -// This is the end of the file - - - - ## execute_command Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Prefer relative commands and paths that avoid location sensitivity for terminal consistency, e.g: `touch ./testdata/example.file`, `dir ./examples/model1/data/yaml`, or `go test ./cmd/front --config ./cmd/front/config.yml`. If directed by the user, you may open a terminal in a different directory by using the `cwd` parameter. Parameters: @@ -494,7 +464,7 @@ CAPABILITIES - When the user initially gives you a task, a recursive list of all filepaths in the current workspace directory ('/test/path') will be included in environment_details. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further. If you need to further explore directories such as outside the current workspace directory, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure, like the Desktop. - You can use search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring. - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task. - - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file or insert_content tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. + - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance. - You have access to MCP servers that may provide additional tools and resources. Each server may provide different capabilities that you can use to accomplish tasks more effectively. @@ -517,9 +487,7 @@ RULES - When using the search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use read_file to examine the full context of interesting matches before using write_to_file to make informed changes. - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser. -- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites), insert_content (for adding lines to files). -- The insert_content tool adds lines of text to files at a specific line number, such as adding a new function to a JavaScript file or inserting a new route in a Python file. Use line number 0 to append at the end of the file, or any positive number to insert before that line. -- You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files. +- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites). - When using the write_to_file tool to modify a file, use the tool directly with the desired content. You do not need to display the content before using the tool. ALWAYS provide the COMPLETE file content in your response. This is NON-NEGOTIABLE. Partial updates or placeholders like '// rest of code unchanged' are STRICTLY FORBIDDEN. You MUST include ALL parts of the file, even if they haven't been modified. Failure to do so will result in incomplete or broken code, severely impacting the user's project. - Some modes have restrictions on which files they can edit. If you attempt to edit a restricted file, the operation will be rejected with a FileRestrictionError that will specify which file patterns are allowed for the current mode. - Be sure to consider the type of project (e.g. Python, JavaScript, web application) when determining the appropriate structure and files to include. Also consider what files may be most relevant to accomplishing the task, for example looking at a project's manifest file would help you understand the project's dependencies, which you could incorporate into any code you write. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-undefined-mcp-hub.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-undefined-mcp-hub.snap index f8392d15496..6a90ff68b0e 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-undefined-mcp-hub.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-undefined-mcp-hub.snap @@ -193,36 +193,6 @@ Example: Requesting to write to frontend-config.json -## insert_content -Description: Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace directory /test/path -- line: (required) Line number where content will be inserted (1-based) - Use 0 to append at end of file - Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: - -src/utils.ts -1 - -// Add imports at start of file -import { sum } from './math'; - - - -Example for appending to the end of file: - -src/utils.ts -0 - -// This is the end of the file - - - - ## execute_command Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Prefer relative commands and paths that avoid location sensitivity for terminal consistency, e.g: `touch ./testdata/example.file`, `dir ./examples/model1/data/yaml`, or `go test ./cmd/front --config ./cmd/front/config.yml`. If directed by the user, you may open a terminal in a different directory by using the `cwd` parameter. Parameters: @@ -428,7 +398,7 @@ CAPABILITIES - When the user initially gives you a task, a recursive list of all filepaths in the current workspace directory ('/test/path') will be included in environment_details. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further. If you need to further explore directories such as outside the current workspace directory, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure, like the Desktop. - You can use search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring. - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task. - - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file or insert_content tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. + - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed. - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance. ==== @@ -449,9 +419,7 @@ RULES - When using the search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use read_file to examine the full context of interesting matches before using write_to_file to make informed changes. - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser. -- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites), insert_content (for adding lines to files). -- The insert_content tool adds lines of text to files at a specific line number, such as adding a new function to a JavaScript file or inserting a new route in a Python file. Use line number 0 to append at the end of the file, or any positive number to insert before that line. -- You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files. +- For editing files, you have access to these tools: write_to_file (for creating new files or complete file rewrites). - When using the write_to_file tool to modify a file, use the tool directly with the desired content. You do not need to display the content before using the tool. ALWAYS provide the COMPLETE file content in your response. This is NON-NEGOTIABLE. Partial updates or placeholders like '// rest of code unchanged' are STRICTLY FORBIDDEN. You MUST include ALL parts of the file, even if they haven't been modified. Failure to do so will result in incomplete or broken code, severely impacting the user's project. - Some modes have restrictions on which files they can edit. If you attempt to edit a restricted file, the operation will be rejected with a FileRestrictionError that will specify which file patterns are allowed for the current mode. - Be sure to consider the type of project (e.g. Python, JavaScript, web application) when determining the appropriate structure and files to include. Also consider what files may be most relevant to accomplishing the task, for example looking at a project's manifest file would help you understand the project's dependencies, which you could incorporate into any code you write. diff --git a/src/core/prompts/__tests__/mode-aware-sections.spec.ts b/src/core/prompts/__tests__/mode-aware-sections.spec.ts index a436055b564..41ad59fd7e0 100644 --- a/src/core/prompts/__tests__/mode-aware-sections.spec.ts +++ b/src/core/prompts/__tests__/mode-aware-sections.spec.ts @@ -19,7 +19,6 @@ describe("Mode-aware system prompt sections", () => { expect(result).toContain("apply_diff") expect(result).toContain("write_to_file") - expect(result).toContain("insert_content") }) it('should NOT include editing tools in "ask" mode', () => { @@ -28,7 +27,6 @@ describe("Mode-aware system prompt sections", () => { // Ask mode doesn't have the "edit" group, so editing tools shouldn't be mentioned expect(result).not.toContain("apply_diff") expect(result).not.toContain("write_to_file") - expect(result).not.toContain("insert_content") }) it('should include editing tools in "architect" mode', () => { @@ -63,7 +61,6 @@ describe("Mode-aware system prompt sections", () => { expect(result).toContain("For editing files") expect(result).toContain("apply_diff") expect(result).toContain("write_to_file") - expect(result).toContain("insert_content") }) it('should NOT include editing instructions in "ask" mode', () => { @@ -82,7 +79,6 @@ describe("Mode-aware system prompt sections", () => { expect(result).not.toContain("For editing files") expect(result).not.toContain("apply_diff") expect(result).not.toContain("write_to_file") - expect(result).not.toContain("insert_content") }) it('should include editing instructions in "debug" mode', () => { diff --git a/src/core/prompts/__tests__/sections.spec.ts b/src/core/prompts/__tests__/sections.spec.ts index 05f16e071c9..69f796cac02 100644 --- a/src/core/prompts/__tests__/sections.spec.ts +++ b/src/core/prompts/__tests__/sections.spec.ts @@ -46,7 +46,6 @@ describe("getCapabilitiesSection", () => { expect(result).toContain("apply_diff") expect(result).toContain("write_to_file") - expect(result).toContain("insert_content") }) it("excludes apply_diff from capabilities when diffStrategy is undefined", () => { @@ -54,7 +53,6 @@ describe("getCapabilitiesSection", () => { expect(result).not.toContain("apply_diff") expect(result).toContain("write_to_file") - expect(result).toContain("insert_content") }) }) diff --git a/src/core/prompts/sections/capabilities.ts b/src/core/prompts/sections/capabilities.ts index 55c7c1f5c30..3b2b4ff2256 100644 --- a/src/core/prompts/sections/capabilities.ts +++ b/src/core/prompts/sections/capabilities.ts @@ -35,7 +35,7 @@ export function getCapabilitiesSection( ) // Build the tool list for the example, filtering for main editing tools - const editingToolsExample = (["apply_diff", "write_to_file", "insert_content"] as const).filter((tool) => { + const editingToolsExample = (["apply_diff", "write_to_file"] as const).filter((tool) => { if (tool === "apply_diff") return diffStrategy && availableEditTools.includes(tool as ToolName) return availableEditTools.includes(tool as ToolName) }) diff --git a/src/core/prompts/sections/rules.ts b/src/core/prompts/sections/rules.ts index 4cc088d6ae4..dc9bc1fbfd6 100644 --- a/src/core/prompts/sections/rules.ts +++ b/src/core/prompts/sections/rules.ts @@ -26,7 +26,6 @@ function getEditingInstructions( // Filter for the main editing tools we care about const hasApplyDiff = diffStrategy && availableEditTools.includes("apply_diff" as ToolName) const hasWriteToFile = availableEditTools.includes("write_to_file" as ToolName) - const hasInsertContent = availableEditTools.includes("insert_content" as ToolName) // If no editing tools are available, return empty string if (availableEditTools.length === 0) { @@ -43,22 +42,12 @@ function getEditingInstructions( if (hasWriteToFile) { availableTools.push("write_to_file (for creating new files or complete file rewrites)") } - if (hasInsertContent) { - availableTools.push("insert_content (for adding lines to files)") - } // Base editing instruction mentioning all available tools if (availableTools.length > 0) { instructions.push(`- For editing files, you have access to these tools: ${availableTools.join(", ")}.`) } - // Additional details for insert_content - if (hasInsertContent) { - instructions.push( - "- The insert_content tool adds lines of text to files at a specific line number, such as adding a new function to a JavaScript file or inserting a new route in a Python file. Use line number 0 to append at the end of the file, or any positive number to insert before that line.", - ) - } - // Preference instruction if multiple tools are available if (availableTools.length > 1 && hasWriteToFile) { instructions.push( diff --git a/src/core/prompts/tools/__tests__/filter-tools-for-mode.spec.ts b/src/core/prompts/tools/__tests__/filter-tools-for-mode.spec.ts index 60aaf14b217..d2ccaa84fb0 100644 --- a/src/core/prompts/tools/__tests__/filter-tools-for-mode.spec.ts +++ b/src/core/prompts/tools/__tests__/filter-tools-for-mode.spec.ts @@ -550,13 +550,13 @@ describe("filterMcpToolsForMode", () => { contextWindow: 100000, supportsPromptCache: false, excludedTools: ["apply_diff"], - includedTools: ["insert_content"], // Another edit tool + includedTools: ["search_and_replace"], // Another edit tool (customTool) } const result = applyModelToolCustomization(tools, codeMode, modelInfo) expect(result.has("read_file")).toBe(true) expect(result.has("write_to_file")).toBe(true) expect(result.has("apply_diff")).toBe(false) // Excluded - expect(result.has("insert_content")).toBe(true) // Included + expect(result.has("search_and_replace")).toBe(true) // Included }) it("should handle empty excludedTools and includedTools arrays", () => { @@ -709,16 +709,16 @@ describe("filterMcpToolsForMode", () => { { type: "function", function: { - name: "insert_content", - description: "Insert content", + name: "execute_command", + description: "Execute command", parameters: {}, }, }, { type: "function", function: { - name: "execute_command", - description: "Execute command", + name: "search_and_replace", + description: "Search and replace", parameters: {}, }, }, @@ -746,7 +746,6 @@ describe("filterMcpToolsForMode", () => { expect(toolNames).toContain("read_file") expect(toolNames).toContain("write_to_file") - expect(toolNames).toContain("insert_content") expect(toolNames).not.toContain("apply_diff") // Excluded by model }) @@ -761,7 +760,7 @@ describe("filterMcpToolsForMode", () => { const modelInfo: ModelInfo = { contextWindow: 100000, supportsPromptCache: false, - includedTools: ["insert_content"], // Edit group tool + includedTools: ["search_and_replace"], // Edit group customTool } const filtered = filterNativeToolsForMode(mockNativeTools, "limited", [modeWithOnlyRead], {}, undefined, { @@ -770,7 +769,7 @@ describe("filterMcpToolsForMode", () => { const toolNames = filtered.map((t) => ("function" in t ? t.function.name : "")) - expect(toolNames).toContain("insert_content") // Included by model + expect(toolNames).toContain("search_and_replace") // Included by model }) it("should NOT include tools from groups not allowed by mode", () => { @@ -810,7 +809,7 @@ describe("filterMcpToolsForMode", () => { contextWindow: 100000, supportsPromptCache: false, excludedTools: ["apply_diff"], - includedTools: ["insert_content"], + includedTools: ["search_and_replace"], } const filtered = filterNativeToolsForMode(mockNativeTools, "code", [codeMode], {}, undefined, { @@ -820,7 +819,7 @@ describe("filterMcpToolsForMode", () => { const toolNames = filtered.map((t) => ("function" in t ? t.function.name : "")) expect(toolNames).toContain("write_to_file") - expect(toolNames).toContain("insert_content") // Included + expect(toolNames).toContain("search_and_replace") // Included expect(toolNames).not.toContain("apply_diff") // Excluded }) }) diff --git a/src/core/prompts/tools/index.ts b/src/core/prompts/tools/index.ts index f00666f38cc..a9e195c166e 100644 --- a/src/core/prompts/tools/index.ts +++ b/src/core/prompts/tools/index.ts @@ -13,7 +13,6 @@ import { shouldUseSingleFileRead } from "@roo-code/types" import { getWriteToFileDescription } from "./write-to-file" import { getSearchFilesDescription } from "./search-files" import { getListFilesDescription } from "./list-files" -import { getInsertContentDescription } from "./insert-content" import { getListCodeDefinitionNamesDescription } from "./list-code-definition-names" import { getBrowserActionDescription } from "./browser-action" import { getAskFollowupQuestionDescription } from "./ask-followup-question" @@ -52,7 +51,6 @@ const toolDescriptionMap: Record string | undefined> codebase_search: (args) => getCodebaseSearchDescription(args), switch_mode: () => getSwitchModeDescription(), new_task: (args) => getNewTaskDescription(args), - insert_content: (args) => getInsertContentDescription(args), apply_diff: (args) => args.diffStrategy ? args.diffStrategy.getToolDescription({ cwd: args.cwd, toolOptions: args.toolOptions }) : "", update_todo_list: (args) => getUpdateTodoListDescription(args), @@ -175,7 +173,6 @@ export { getUseMcpToolDescription, getAccessMcpResourceDescription, getSwitchModeDescription, - getInsertContentDescription, getCodebaseSearchDescription, getRunSlashCommandDescription, getGenerateImageDescription, diff --git a/src/core/prompts/tools/insert-content.ts b/src/core/prompts/tools/insert-content.ts deleted file mode 100644 index 7e339513d5e..00000000000 --- a/src/core/prompts/tools/insert-content.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ToolArgs } from "./types" - -export function getInsertContentDescription(args: ToolArgs): string { - return `## insert_content -Description: Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace directory ${args.cwd.toPosix()} -- line: (required) Line number where content will be inserted (1-based) - Use 0 to append at end of file - Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: - -src/utils.ts -1 - -// Add imports at start of file -import { sum } from './math'; - - - -Example for appending to the end of file: - -src/utils.ts -0 - -// This is the end of the file - - -` -} diff --git a/src/core/prompts/tools/native-tools/index.ts b/src/core/prompts/tools/native-tools/index.ts index 1ffd9b8c934..1cb0baab837 100644 --- a/src/core/prompts/tools/native-tools/index.ts +++ b/src/core/prompts/tools/native-tools/index.ts @@ -9,7 +9,6 @@ import codebaseSearch from "./codebase_search" import executeCommand from "./execute_command" import fetchInstructions from "./fetch_instructions" import generateImage from "./generate_image" -import insertContent from "./insert_content" import listCodeDefinitionNames from "./list_code_definition_names" import listFiles from "./list_files" import newTask from "./new_task" @@ -42,7 +41,6 @@ export function getNativeTools(partialReadsEnabled: boolean = true): OpenAI.Chat executeCommand, fetchInstructions, generateImage, - insertContent, listCodeDefinitionNames, listFiles, newTask, diff --git a/src/core/prompts/tools/native-tools/insert_content.ts b/src/core/prompts/tools/native-tools/insert_content.ts deleted file mode 100644 index b39a09dab0f..00000000000 --- a/src/core/prompts/tools/native-tools/insert_content.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type OpenAI from "openai" - -const INSERT_CONTENT_DESCRIPTION = `Use this tool specifically for adding new lines of content into a file without modifying existing content. Specify the line number to insert before, or use line 0 to append to the end. Ideal for adding imports, functions, configuration blocks, log entries, or any multi-line text block. - -Parameters: -- path: (required) File path relative to workspace -- line: (required) Line number where content will be inserted (1-based). Use 0 to append at end of file. Use any positive number to insert before that line -- content: (required) The content to insert at the specified line - -Example for inserting imports at start of file: -{ "path": "src/utils.ts", "line": 1, "content": "// Add imports at start of file\\nimport { sum } from './math';" } - -Example for appending to the end of file: -{ "path": "src/utils.ts", "line": 0, "content": "// This is the end of the file" }` - -const PATH_PARAMETER_DESCRIPTION = `File path to modify, expressed relative to the workspace` - -const LINE_PARAMETER_DESCRIPTION = `1-based line number to insert before, or 0 to append at the end of the file` - -const CONTENT_PARAMETER_DESCRIPTION = `Exact text to insert at the chosen location` - -export default { - type: "function", - function: { - name: "insert_content", - description: INSERT_CONTENT_DESCRIPTION, - strict: true, - parameters: { - type: "object", - properties: { - path: { - type: "string", - description: PATH_PARAMETER_DESCRIPTION, - }, - line: { - type: "integer", - description: LINE_PARAMETER_DESCRIPTION, - minimum: 0, - }, - content: { - type: "string", - description: CONTENT_PARAMETER_DESCRIPTION, - }, - }, - required: ["path", "line", "content"], - additionalProperties: false, - }, - }, -} satisfies OpenAI.Chat.ChatCompletionTool diff --git a/src/core/task-persistence/apiMessages.ts b/src/core/task-persistence/apiMessages.ts index abfd0b68399..1366ce6b787 100644 --- a/src/core/task-persistence/apiMessages.ts +++ b/src/core/task-persistence/apiMessages.ts @@ -20,6 +20,18 @@ export type ApiMessage = Anthropic.MessageParam & { text?: string // For OpenRouter reasoning_details array format (used by Gemini 3, etc.) reasoning_details?: any[] + // For non-destructive condense: unique identifier for summary messages + condenseId?: string + // For non-destructive condense: points to the condenseId of the summary that replaces this message + // Messages with condenseParent are filtered out when sending to API if the summary exists + condenseParent?: string + // For non-destructive truncation: unique identifier for truncation marker messages + truncationId?: string + // For non-destructive truncation: points to the truncationId of the marker that hides this message + // Messages with truncationParent are filtered out when sending to API if the marker exists + truncationParent?: string + // Identifies a message as a truncation boundary marker + isTruncationMarker?: boolean } export async function readApiMessages({ diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index 81854fb2155..d808927248a 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -21,6 +21,7 @@ import { type ToolUsage, type ToolName, type ContextCondense, + type ContextTruncation, type ClineMessage, type ClineSay, type ClineAsk, @@ -122,7 +123,7 @@ import { checkpointDiff, } from "../checkpoints" import { processUserContentMentions } from "../mentions/processUserContentMentions" -import { getMessagesSinceLastSummary, summarizeConversation } from "../condense" +import { getMessagesSinceLastSummary, summarizeConversation, getEffectiveApiHistory } from "../condense" import { MessageQueueService } from "../message-queue/MessageQueueService" import { ErrorCodeManager } from "../costrict/error-code" @@ -1418,6 +1419,7 @@ export class Task extends EventEmitter implements TaskLike { cost, newContextTokens = 0, error, + condenseId, } = await summarizeConversation( this.apiConversationHistory, this.api, // Main API handler (fallback) @@ -1443,7 +1445,13 @@ export class Task extends EventEmitter implements TaskLike { } await this.overwriteApiConversationHistory(messages) - const contextCondense: ContextCondense = { summary, cost, newContextTokens, prevContextTokens } + const contextCondense: ContextCondense = { + summary, + cost, + newContextTokens, + prevContextTokens, + condenseId: condenseId!, + } await this.say( "condense_context", undefined /* text */, @@ -1472,6 +1480,7 @@ export class Task extends EventEmitter implements TaskLike { [key: string]: any } = {}, contextCondense?: ContextCondense, + contextTruncation?: ContextTruncation, ): Promise { if (this.abort) { throw new Error(`[CoStrict#say] task ${this.taskId}.${this.instanceId} aborted`) @@ -1511,6 +1520,7 @@ export class Task extends EventEmitter implements TaskLike { partial, contextCondense, metadata: { isRateLimitRetry }, + contextTruncation, }) } } else { @@ -1550,6 +1560,7 @@ export class Task extends EventEmitter implements TaskLike { subtaskId: options.subtaskId, images, contextCondense, + contextTruncation, }) } } @@ -1574,6 +1585,7 @@ export class Task extends EventEmitter implements TaskLike { images, checkpoint, contextCondense, + contextTruncation, }) } @@ -3503,6 +3515,24 @@ export class Task extends EventEmitter implements TaskLike { { isNonInteractive: true } /* options */, contextCondense, ) + } else if (truncateResult.truncationId) { + // Sliding window truncation occurred (fallback when condensing fails or is disabled) + const contextTruncation: ContextTruncation = { + truncationId: truncateResult.truncationId, + messagesRemoved: truncateResult.messagesRemoved ?? 0, + prevContextTokens: truncateResult.prevContextTokens, + } + await this.say( + "sliding_window_truncation", + undefined /* text */, + undefined /* images */, + false /* partial */, + undefined /* checkpoint */, + undefined /* progressStatus */, + { isNonInteractive: true } /* options */, + undefined /* contextCondense */, + contextTruncation, + ) } } @@ -3614,8 +3644,14 @@ export class Task extends EventEmitter implements TaskLike { if (truncateResult.error) { await this.say("condense_context_error", truncateResult.error) } else if (truncateResult.summary) { - const { summary, cost, prevContextTokens, newContextTokens = 0 } = truncateResult - const contextCondense: ContextCondense = { summary, cost, newContextTokens, prevContextTokens } + const { summary, cost, prevContextTokens, newContextTokens = 0, condenseId } = truncateResult + const contextCondense: ContextCondense = { + summary, + cost, + newContextTokens, + prevContextTokens, + condenseId, + } await this.say( "condense_context", undefined /* text */, @@ -3626,10 +3662,32 @@ export class Task extends EventEmitter implements TaskLike { { isNonInteractive: true } /* options */, contextCondense, ) + } else if (truncateResult.truncationId) { + // Sliding window truncation occurred (fallback when condensing fails or is disabled) + const contextTruncation: ContextTruncation = { + truncationId: truncateResult.truncationId, + messagesRemoved: truncateResult.messagesRemoved ?? 0, + prevContextTokens: truncateResult.prevContextTokens, + } + await this.say( + "sliding_window_truncation", + undefined /* text */, + undefined /* images */, + false /* partial */, + undefined /* checkpoint */, + undefined /* progressStatus */, + { isNonInteractive: true } /* options */, + undefined /* contextCondense */, + contextTruncation, + ) } } - const messagesSinceLastSummary = getMessagesSinceLastSummary(this.apiConversationHistory) + // Get the effective API history by filtering out condensed messages + // This allows non-destructive condensing where messages are tagged but not deleted, + // enabling accurate rewind operations while still sending condensed history to the API. + const effectiveHistory = getEffectiveApiHistory(this.apiConversationHistory) + const messagesSinceLastSummary = getMessagesSinceLastSummary(effectiveHistory) const messagesWithoutImages = maybeRemoveImageBlocks(messagesSinceLastSummary, this.api) const cleanConversationHistory = this.buildCleanConversationHistory(messagesWithoutImages as ApiMessage[]) @@ -3674,11 +3732,14 @@ export class Task extends EventEmitter implements TaskLike { } const { id } = (await ZgsmAuthService.getInstance()?.getUserInfo()) ?? {} - // Resolve parallel tool calls setting from experiment (will move to per-API-profile setting later) - const parallelToolCallsEnabled = experiments.isEnabled( - state?.experiments ?? {}, - EXPERIMENT_IDS.MULTIPLE_NATIVE_TOOL_CALLS, - ) + // // Resolve parallel tool calls setting from experiment (will move to per-API-profile setting later) + // const parallelToolCallsEnabled = experiments.isEnabled( + // state?.experiments ?? {}, + // EXPERIMENT_IDS.MULTIPLE_NATIVE_TOOL_CALLS, + // ) + // Parallel tool calls are disabled - feature is on hold + // Previously resolved from experiments.isEnabled(..., EXPERIMENT_IDS.MULTIPLE_NATIVE_TOOL_CALLS) + const parallelToolCallsEnabled = false const metadata: ApiHandlerCreateMessageMetadata = { mode: mode, diff --git a/src/core/task/__tests__/native-tools-filtering.spec.ts b/src/core/task/__tests__/native-tools-filtering.spec.ts index ff7c7a104ab..a32bd2cd0ce 100644 --- a/src/core/task/__tests__/native-tools-filtering.spec.ts +++ b/src/core/task/__tests__/native-tools-filtering.spec.ts @@ -44,7 +44,6 @@ describe("Native Tools Filtering by Mode", () => { // Architect should NOT have edit tools expect(architectAllowedTools.has("write_to_file")).toBe(false) expect(architectAllowedTools.has("apply_diff")).toBe(false) - expect(architectAllowedTools.has("insert_content")).toBe(false) // Architect SHOULD have read tools expect(architectAllowedTools.has("read_file")).toBe(true) @@ -72,7 +71,6 @@ describe("Native Tools Filtering by Mode", () => { // Code SHOULD have edit tools expect(codeAllowedTools.has("write_to_file")).toBe(true) expect(codeAllowedTools.has("apply_diff")).toBe(true) - expect(codeAllowedTools.has("insert_content")).toBe(true) // Code SHOULD have read tools expect(codeAllowedTools.has("read_file")).toBe(true) diff --git a/src/core/tools/InsertContentTool.ts b/src/core/tools/InsertContentTool.ts deleted file mode 100644 index f998d1c4ed2..00000000000 --- a/src/core/tools/InsertContentTool.ts +++ /dev/null @@ -1,226 +0,0 @@ -import fs from "fs/promises" -import path from "path" - -import { getReadablePath } from "../../utils/path" -import { Task } from "../task/Task" -import { formatResponse } from "../prompts/responses" -import { ClineSayTool } from "../../shared/ExtensionMessage" -import { RecordSource } from "../context-tracking/FileContextTrackerTypes" -import { fileExistsAtPath } from "../../utils/fs" -import { insertGroups } from "../diff/insert-groups" -import { DEFAULT_WRITE_DELAY_MS } from "@roo-code/types" -import { EXPERIMENT_IDS, experiments } from "../../shared/experiments" -import { convertNewFileToUnifiedDiff, computeDiffStats, sanitizeUnifiedDiff } from "../diff/stats" -import { BaseTool, ToolCallbacks } from "./BaseTool" -import type { ToolUse } from "../../shared/tools" - -interface InsertContentParams { - path: string - line: number - content: string -} - -export class InsertContentTool extends BaseTool<"insert_content"> { - readonly name = "insert_content" as const - - parseLegacy(params: Partial>): InsertContentParams { - const relPath = params.path || "" - const lineStr = params.line || "" - const content = params.content || "" - - const lineNumber = parseInt(lineStr, 10) - - return { - path: relPath, - line: lineNumber, - content: content, - } - } - - async execute(params: InsertContentParams, task: Task, callbacks: ToolCallbacks): Promise { - const { path: relPath, line: lineNumber, content } = params - const { askApproval, handleError, pushToolResult, toolProtocol } = callbacks - - try { - // Validate required parameters - if (!relPath) { - task.consecutiveMistakeCount++ - task.recordToolError("insert_content") - pushToolResult(await task.sayAndCreateMissingParamError("insert_content", "path")) - return - } - - if (isNaN(lineNumber) || lineNumber < 0) { - task.consecutiveMistakeCount++ - task.recordToolError("insert_content") - pushToolResult(formatResponse.toolError("Invalid line number. Must be a non-negative integer.")) - return - } - - if (content === undefined) { - task.consecutiveMistakeCount++ - task.recordToolError("insert_content") - pushToolResult(await task.sayAndCreateMissingParamError("insert_content", "content")) - return - } - - const accessAllowed = task.rooIgnoreController?.validateAccess(relPath) - - if (!accessAllowed) { - await task.say("rooignore_error", relPath) - pushToolResult(formatResponse.rooIgnoreError(relPath, toolProtocol)) - return - } - - // Check if file is write-protected - const isWriteProtected = task.rooProtectedController?.isWriteProtected(relPath) || false - - const absolutePath = path.resolve(task.cwd, relPath) - - const fileExists = await fileExistsAtPath(absolutePath) - let fileContent: string = "" - if (!fileExists) { - if (lineNumber > 1) { - task.consecutiveMistakeCount++ - task.recordToolError("insert_content") - const formattedError = `Cannot insert content at line ${lineNumber} into a non-existent file. For new files, 'line' must be 0 (to append) or 1 (to insert at the beginning).` - await task.say("error", formattedError) - task.didToolFailInCurrentTurn = true - pushToolResult(formattedError) - return - } - } else { - fileContent = await fs.readFile(absolutePath, "utf8") - } - - task.consecutiveMistakeCount = 0 - - task.diffViewProvider.editType = fileExists ? "modify" : "create" - task.diffViewProvider.originalContent = fileContent - const lines = fileExists ? fileContent.split("\n") : [] - - let updatedContent = insertGroups(lines, [ - { - index: lineNumber - 1, - elements: content.split("\n"), - }, - ]).join("\n") - - // Check if preventFocusDisruption experiment is enabled - const provider = task.providerRef.deref() - const state = await provider?.getState() - const diagnosticsEnabled = state?.diagnosticsEnabled ?? true - const writeDelayMs = state?.writeDelayMs ?? DEFAULT_WRITE_DELAY_MS - const isPreventFocusDisruptionEnabled = experiments.isEnabled( - state?.experiments ?? {}, - EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION, - ) - - // Build unified diff for display (normalize EOLs only for diff generation) - let unified: string - if (fileExists) { - const oldForDiff = fileContent.replace(/\r\n/g, "\n") - const newForDiff = updatedContent.replace(/\r\n/g, "\n") - unified = formatResponse.createPrettyPatch(relPath, oldForDiff, newForDiff) - if (!unified) { - pushToolResult(`No changes needed for '${relPath}'`) - return - } - } else { - const newForDiff = updatedContent.replace(/\r\n/g, "\n") - unified = convertNewFileToUnifiedDiff(newForDiff, relPath) - } - unified = sanitizeUnifiedDiff(unified) - const diffStats = computeDiffStats(unified) || undefined - - // Prepare the approval message (same for both flows) - const sharedMessageProps: ClineSayTool = { - tool: "insertContent", - path: getReadablePath(task.cwd, relPath), - diff: content, - lineNumber: lineNumber, - } - - const completeMessage = JSON.stringify({ - ...sharedMessageProps, - // Send unified diff as content for render-only webview - content: unified, - lineNumber: lineNumber, - isProtected: isWriteProtected, - diffStats, - } satisfies ClineSayTool) - - // Show diff view if focus disruption prevention is disabled - if (!isPreventFocusDisruptionEnabled) { - await task.diffViewProvider.open(relPath) - await task.diffViewProvider.update(updatedContent, true) - task.diffViewProvider.scrollToFirstDiff() - } - - // Ask for approval (same for both flows) - const didApprove = await askApproval("tool", completeMessage, undefined, isWriteProtected) - - if (!didApprove) { - // Revert changes if diff view was shown - if (!isPreventFocusDisruptionEnabled) { - await task.diffViewProvider.revertChanges() - } - pushToolResult("Changes were rejected by the user.") - await task.diffViewProvider.reset() - return - } - - // Save the changes - if (isPreventFocusDisruptionEnabled) { - // Direct file write without diff view or opening the file - await task.diffViewProvider.saveDirectly( - relPath, - updatedContent, - false, - diagnosticsEnabled, - writeDelayMs, - ) - } else { - // Call saveChanges to update the DiffViewProvider properties - await task.diffViewProvider.saveChanges(diagnosticsEnabled, writeDelayMs) - } - - // Track file edit operation - if (relPath) { - await task.fileContextTracker.trackFileContext(relPath, "roo_edited" as RecordSource) - } - - task.didEditFile = true - - // Get the formatted response message - const message = await task.diffViewProvider.pushToolWriteResult(task, task.cwd, !fileExists) - - pushToolResult(message) - - await task.diffViewProvider.reset() - - // Process any queued messages after file edit completes - task.processQueuedMessages() - } catch (error) { - await handleError("insert content", error as Error) - await task.diffViewProvider.reset() - } - } - - override async handlePartial(task: Task, block: ToolUse<"insert_content">): Promise { - const relPath: string | undefined = block.params.path - const line: string | undefined = block.params.line - const content: string | undefined = block.params.content - - const sharedMessageProps: ClineSayTool = { - tool: "insertContent", - path: getReadablePath(task.cwd, relPath || ""), - diff: content, - lineNumber: line ? parseInt(line, 10) : undefined, - } - - await task.ask("tool", JSON.stringify(sharedMessageProps), block.partial).catch(() => {}) - } -} - -export const insertContentTool = new InsertContentTool() diff --git a/src/core/tools/WriteToFileTool.ts b/src/core/tools/WriteToFileTool.ts index f1bae7ff2fc..7caaeb6d55d 100644 --- a/src/core/tools/WriteToFileTool.ts +++ b/src/core/tools/WriteToFileTool.ts @@ -11,7 +11,6 @@ import { fileExistsAtPath, createDirectoriesForFile } from "../../utils/fs" import { stripLineNumbers, everyLineHasLineNumbers } from "../../integrations/misc/extract-text" import { getReadablePath } from "../../utils/path" import { isPathOutsideWorkspace } from "../../utils/pathUtils" -import { detectCodeOmission } from "../../integrations/editor/detect-omission" import { unescapeHtmlEntities } from "../../utils/text-normalization" import { DEFAULT_WRITE_DELAY_MS } from "@roo-code/types" import { EXPERIMENT_IDS, experiments } from "../../shared/experiments" @@ -125,32 +124,6 @@ export class WriteToFileTool extends BaseTool<"write_to_file"> { task.diffViewProvider.originalContent = "" } - if (detectCodeOmission(task.diffViewProvider.originalContent || "", newContent)) { - if (task.diffStrategy) { - pushToolResult( - formatResponse.toolError( - `Content appears to contain comments indicating omitted code (e.g., '// rest of code unchanged', '/* previous code */'). Please provide the complete file content without any omissions if possible, or otherwise use the 'apply_diff' tool to apply the diff to the original file.`, - ), - ) - return - } else { - vscode.window - .showWarningMessage( - "Potential code truncation detected. This happens when the AI reaches its max output limit.", - "Follow guide to fix the issue", - ) - .then((selection) => { - if (selection === "Follow guide to fix the issue") { - vscode.env.openExternal( - vscode.Uri.parse( - "https://github.com/cline/cline/wiki/Troubleshooting-%E2%80%90-Cline-Deleting-Code-with-%22Rest-of-Code-Here%22-Comments", - ), - ) - } - }) - } - } - let unified = fileExists ? formatResponse.createPrettyPatch(relPath, task.diffViewProvider.originalContent, newContent) : convertNewFileToUnifiedDiff(newContent, relPath) @@ -183,34 +156,6 @@ export class WriteToFileTool extends BaseTool<"write_to_file"> { await delay(300) task.diffViewProvider.scrollToFirstDiff() - if (detectCodeOmission(task.diffViewProvider.originalContent || "", newContent)) { - if (task.diffStrategy) { - await task.diffViewProvider.revertChanges() - - pushToolResult( - formatResponse.toolError( - `Content appears to contain comments indicating omitted code (e.g., '// rest of code unchanged', '/* previous code */'). Please provide the complete file content without any omissions if possible, or otherwise use the 'apply_diff' tool to apply the diff to the original file.`, - ), - ) - return - } else { - vscode.window - .showWarningMessage( - "Potential code truncation detected. This happens when the AI reaches its max output limit.", - "Follow guide to fix the issue", - ) - .then((selection) => { - if (selection === "Follow guide to fix the issue") { - vscode.env.openExternal( - vscode.Uri.parse( - "https://github.com/cline/cline/wiki/Troubleshooting-%E2%80%90-Cline-Deleting-Code-with-%22Rest-of-Code-Here%22-Comments", - ), - ) - } - }) - } - } - let unified = fileExists ? formatResponse.createPrettyPatch(relPath, task.diffViewProvider.originalContent, newContent) : convertNewFileToUnifiedDiff(newContent, relPath) diff --git a/src/core/tools/__tests__/insertContentTool.spec.ts b/src/core/tools/__tests__/insertContentTool.spec.ts deleted file mode 100644 index 4f158d3c618..00000000000 --- a/src/core/tools/__tests__/insertContentTool.spec.ts +++ /dev/null @@ -1,234 +0,0 @@ -import * as fs from "fs/promises" -import * as path from "path" -import type { MockedFunction } from "vitest" - -import { fileExistsAtPath } from "../../../utils/fs" -import { ToolUse, ToolResponse } from "../../../shared/tools" -import { insertContentTool } from "../InsertContentTool" - -// Helper to normalize paths to POSIX format for cross-platform testing -const toPosix = (filePath: string) => filePath.replace(/\\/g, "/") - -// Mock external dependencies -vi.mock("fs/promises", () => ({ - readFile: vi.fn(), - writeFile: vi.fn(), -})) - -vi.mock("delay", () => ({ - default: vi.fn(), -})) - -vi.mock("../../../utils/fs", () => ({ - fileExistsAtPath: vi.fn().mockResolvedValue(false), -})) - -vi.mock("../../prompts/responses", () => ({ - formatResponse: { - toolError: vi.fn((msg) => `Error: ${msg}`), - rooIgnoreError: vi.fn((path) => `Access denied: ${path}`), - createPrettyPatch: vi.fn((_path, original, updated) => `Diff: ${original} -> ${updated}`), - }, -})) - -vi.mock("../../../utils/path", () => ({ - getReadablePath: vi.fn().mockReturnValue("test/path.txt"), - getWorkspacePath: vi.fn().mockReturnValue("/test/workspace"), -})) - -vi.mock("../../ignore/RooIgnoreController", () => ({ - RooIgnoreController: class { - initialize() { - return Promise.resolve() - } - validateAccess() { - return true - } - }, -})) - -describe("insertContentTool", () => { - const testFilePath = "test/file.txt" - // Use a consistent mock absolute path for testing - const absoluteFilePath = "/test/file.txt" - - const mockedFileExistsAtPath = fileExistsAtPath as MockedFunction - const mockedFsReadFile = fs.readFile as MockedFunction - - let mockCline: any - let mockAskApproval: ReturnType - let mockHandleError: ReturnType - let mockPushToolResult: ReturnType - let mockRemoveClosingTag: ReturnType - let toolResult: ToolResponse | undefined - - beforeEach(() => { - vi.clearAllMocks() - - mockedFileExistsAtPath.mockResolvedValue(true) // Assume file exists by default for insert - mockedFsReadFile.mockResolvedValue("") // Default empty file content - - mockCline = { - cwd: "/", - consecutiveMistakeCount: 0, - didEditFile: false, - providerRef: { - deref: vi.fn().mockReturnValue({ - getState: vi.fn().mockResolvedValue({ - diagnosticsEnabled: true, - writeDelayMs: 1000, - }), - }), - }, - rooIgnoreController: { - validateAccess: vi.fn().mockReturnValue(true), - }, - diffViewProvider: { - editType: undefined, - isEditing: false, - originalContent: "", - open: vi.fn().mockResolvedValue(undefined), - update: vi.fn().mockResolvedValue(undefined), - reset: vi.fn().mockResolvedValue(undefined), - revertChanges: vi.fn().mockResolvedValue(undefined), - saveChanges: vi.fn().mockResolvedValue({ - newProblemsMessage: "", - userEdits: null, - finalContent: "final content", - }), - scrollToFirstDiff: vi.fn(), - updateDiagnosticSettings: vi.fn(), - pushToolWriteResult: vi.fn().mockImplementation(async function ( - this: any, - task: any, - cwd: string, - isNewFile: boolean, - ) { - return "Tool result message" - }), - }, - fileContextTracker: { - trackFileContext: vi.fn().mockResolvedValue(undefined), - }, - say: vi.fn().mockResolvedValue(undefined), - ask: vi.fn().mockResolvedValue({ response: "yesButtonClicked" }), // Default to approval - recordToolError: vi.fn(), - sayAndCreateMissingParamError: vi.fn().mockResolvedValue("Missing param error"), - } - - mockAskApproval = vi.fn().mockResolvedValue(true) - mockHandleError = vi.fn().mockResolvedValue(undefined) - mockRemoveClosingTag = vi.fn((tag, content) => content) - - toolResult = undefined - }) - - async function executeInsertContentTool( - params: Partial = {}, - options: { - fileExists?: boolean - isPartial?: boolean - accessAllowed?: boolean - fileContent?: string - askApprovalResponse?: "yesButtonClicked" | "noButtonClicked" | string - } = {}, - ): Promise { - const fileExists = options.fileExists ?? true - const isPartial = options.isPartial ?? false - const accessAllowed = options.accessAllowed ?? true - const fileContent = options.fileContent ?? "" - - mockedFileExistsAtPath.mockResolvedValue(fileExists) - mockedFsReadFile.mockResolvedValue(fileContent) - mockCline.rooIgnoreController.validateAccess.mockReturnValue(accessAllowed) - mockCline.ask.mockResolvedValue({ response: options.askApprovalResponse ?? "yesButtonClicked" }) - - const toolUse: ToolUse = { - type: "tool_use", - name: "insert_content", - params: { - path: testFilePath, - line: "1", - content: "New content", - ...params, - }, - partial: isPartial, - } - - await insertContentTool.handle(mockCline, toolUse as any, { - askApproval: mockAskApproval, - handleError: mockHandleError, - pushToolResult: (result: ToolResponse) => { - toolResult = result - }, - removeClosingTag: mockRemoveClosingTag, - toolProtocol: "xml", - }) - - return toolResult - } - - describe("new file creation logic", () => { - it("creates a new file and inserts content at line 0 (append)", async () => { - const contentToInsert = "New Line 1\nNew Line 2" - await executeInsertContentTool( - { line: "0", content: contentToInsert }, - { fileExists: false, fileContent: "" }, - ) - - // Normalize the path that was called with to POSIX format for comparison - const calledPath = mockedFileExistsAtPath.mock.calls[0][0] - expect(toPosix(calledPath)).toContain(testFilePath) - expect(mockedFsReadFile).not.toHaveBeenCalled() // Should not read if file doesn't exist - expect(mockCline.diffViewProvider.update).toHaveBeenCalledWith(contentToInsert, true) - expect(mockCline.diffViewProvider.editType).toBe("create") - expect(mockCline.diffViewProvider.pushToolWriteResult).toHaveBeenCalledWith(mockCline, mockCline.cwd, true) - }) - - it("creates a new file and inserts content at line 1 (beginning)", async () => { - const contentToInsert = "Hello World!" - await executeInsertContentTool( - { line: "1", content: contentToInsert }, - { fileExists: false, fileContent: "" }, - ) - - // Normalize the path that was called with to POSIX format for comparison - const calledPath = mockedFileExistsAtPath.mock.calls[0][0] - expect(toPosix(calledPath)).toContain(testFilePath) - expect(mockedFsReadFile).not.toHaveBeenCalled() - expect(mockCline.diffViewProvider.update).toHaveBeenCalledWith(contentToInsert, true) - expect(mockCline.diffViewProvider.editType).toBe("create") - expect(mockCline.diffViewProvider.pushToolWriteResult).toHaveBeenCalledWith(mockCline, mockCline.cwd, true) - }) - - it("creates an empty new file if content is empty string", async () => { - await executeInsertContentTool({ line: "1", content: "" }, { fileExists: false, fileContent: "" }) - - // Normalize the path that was called with to POSIX format for comparison - const calledPath = mockedFileExistsAtPath.mock.calls[0][0] - expect(toPosix(calledPath)).toContain(testFilePath) - expect(mockedFsReadFile).not.toHaveBeenCalled() - expect(mockCline.diffViewProvider.update).toHaveBeenCalledWith("", true) - expect(mockCline.diffViewProvider.editType).toBe("create") - expect(mockCline.diffViewProvider.pushToolWriteResult).toHaveBeenCalledWith(mockCline, mockCline.cwd, true) - }) - - it("returns an error when inserting content at an arbitrary line number into a new file", async () => { - const contentToInsert = "Arbitrary insert" - const result = await executeInsertContentTool( - { line: "5", content: contentToInsert }, - { fileExists: false, fileContent: "" }, - ) - - // Normalize the path that was called with to POSIX format for comparison - const calledPath = mockedFileExistsAtPath.mock.calls[0][0] - expect(toPosix(calledPath)).toContain(testFilePath) - expect(mockedFsReadFile).not.toHaveBeenCalled() - expect(mockCline.consecutiveMistakeCount).toBe(1) - expect(mockCline.recordToolError).toHaveBeenCalledWith("insert_content") - expect(mockCline.say).toHaveBeenCalledWith("error", expect.stringContaining("non-existent file")) - expect(mockCline.diffViewProvider.update).not.toHaveBeenCalled() - expect(mockCline.diffViewProvider.pushToolWriteResult).not.toHaveBeenCalled() - }) - }) -}) diff --git a/src/core/tools/__tests__/writeToFileTool.spec.ts b/src/core/tools/__tests__/writeToFileTool.spec.ts index fffa1f07fd2..a8a7021ebfb 100644 --- a/src/core/tools/__tests__/writeToFileTool.spec.ts +++ b/src/core/tools/__tests__/writeToFileTool.spec.ts @@ -3,7 +3,6 @@ import * as path from "path" import type { MockedFunction } from "vitest" import { fileExistsAtPath, createDirectoriesForFile } from "../../../utils/fs" -import { detectCodeOmission } from "../../../integrations/editor/detect-omission" import { isPathOutsideWorkspace } from "../../../utils/pathUtils" import { getReadablePath } from "../../../utils/path" import { unescapeHtmlEntities } from "../../../utils/text-normalization" @@ -40,10 +39,6 @@ vi.mock("../../prompts/responses", () => ({ }, })) -vi.mock("../../../integrations/editor/detect-omission", () => ({ - detectCodeOmission: vi.fn().mockReturnValue(false), -})) - vi.mock("../../../utils/pathUtils", () => ({ isPathOutsideWorkspace: vi.fn().mockReturnValue(false), })) @@ -111,7 +106,6 @@ describe("writeToFileTool", () => { // Mocked functions with correct types const mockedFileExistsAtPath = fileExistsAtPath as MockedFunction const mockedCreateDirectoriesForFile = createDirectoriesForFile as MockedFunction - const mockedDetectCodeOmission = detectCodeOmission as MockedFunction const mockedIsPathOutsideWorkspace = isPathOutsideWorkspace as MockedFunction const mockedGetReadablePath = getReadablePath as MockedFunction const mockedUnescapeHtmlEntities = unescapeHtmlEntities as MockedFunction @@ -131,7 +125,6 @@ describe("writeToFileTool", () => { mockedPathResolve.mockReturnValue(absoluteFilePath) mockedFileExistsAtPath.mockResolvedValue(false) - mockedDetectCodeOmission.mockReturnValue(false) mockedIsPathOutsideWorkspace.mockReturnValue(false) mockedGetReadablePath.mockReturnValue("test/path.txt") mockedUnescapeHtmlEntities.mockImplementation((content) => content) diff --git a/src/core/webview/__tests__/webviewMessageHandler.delete.spec.ts b/src/core/webview/__tests__/webviewMessageHandler.delete.spec.ts index 7d67bed4cb6..08c2a9d64ff 100644 --- a/src/core/webview/__tests__/webviewMessageHandler.delete.spec.ts +++ b/src/core/webview/__tests__/webviewMessageHandler.delete.spec.ts @@ -253,5 +253,322 @@ describe("webviewMessageHandler delete functionality", () => { { ts: 1500, role: "assistant", content: { type: "text", text: "First response" } }, ]) }) + + describe("condense preservation behavior", () => { + it("should preserve summary and condensed messages when deleting after the summary", async () => { + // Design: Rewind/delete preserves summaries that were created BEFORE the rewind point. + // Only summaries removed by truncation have their associated condenseParent tags cleared. + const condenseId = "summary-abc" + + getCurrentTaskMock.clineMessages = [ + { ts: 100, say: "user", text: "First message" }, + { ts: 200, say: "assistant", text: "Response 1" }, + { ts: 300, say: "user", text: "Second message" }, + { ts: 799, say: "assistant", text: "Summary" }, + { ts: 800, say: "assistant", text: "Kept message 1" }, + { ts: 900, say: "user", text: "Kept message 2" }, + { ts: 1000, say: "assistant", text: "Kept message 3" }, + ] + + // API history after condense: msg1, msg2(tagged), msg3(tagged), summary, kept1, kept2, kept3 + getCurrentTaskMock.apiConversationHistory = [ + { ts: 100, role: "user", content: "First message" }, + { ts: 200, role: "assistant", content: "Response 1", condenseParent: condenseId }, + { ts: 300, role: "user", content: "Second message", condenseParent: condenseId }, + { ts: 799, role: "assistant", content: "Summary", isSummary: true, condenseId }, + { ts: 800, role: "assistant", content: "Kept message 1" }, + { ts: 900, role: "user", content: "Kept message 2" }, + { ts: 1000, role: "assistant", content: "Kept message 3" }, + ] + + // Delete kept message 2 (ts=900) - summary is BEFORE truncation point so should be preserved + await webviewMessageHandler(provider, { + type: "deleteMessageConfirm", + messageTs: 900, + }) + + expect(getCurrentTaskMock.overwriteApiConversationHistory).toHaveBeenCalled() + const result = getCurrentTaskMock.overwriteApiConversationHistory.mock.calls[0][0] + + // Summary should be PRESERVED, condensed messages should KEEP their tags + // Expected: [msg1, msg2(tagged), msg3(tagged), summary, kept1] + expect(result.length).toBe(5) + expect(result[0].content).toBe("First message") + expect(result[1].content).toBe("Response 1") + expect(result[1].condenseParent).toBe(condenseId) // Tag preserved + expect(result[2].content).toBe("Second message") + expect(result[2].condenseParent).toBe(condenseId) // Tag preserved + expect(result[3].content).toBe("Summary") + expect(result[3].isSummary).toBe(true) // Summary preserved + expect(result[4].content).toBe("Kept message 1") + }) + + it("should restore condensed messages when summary is removed by truncation", async () => { + // Scenario: Condensed messages exist, user deletes in a way that removes the summary + // The orphaned condenseParent tags should be cleared + const condenseId = "summary-xyz" + + getCurrentTaskMock.clineMessages = [ + { ts: 100, say: "user", text: "Task start" }, + { ts: 200, say: "assistant", text: "Response 1" }, + { ts: 300, say: "user", text: "Message 2" }, + { ts: 999, say: "assistant", text: "Summary displayed" }, + { ts: 1000, say: "user", text: "First kept" }, + ] + + // API history with condensed messages and summary + getCurrentTaskMock.apiConversationHistory = [ + { ts: 100, role: "user", content: "Task start" }, + { ts: 200, role: "assistant", content: "Response 1", condenseParent: condenseId }, + { ts: 300, role: "user", content: "Message 2", condenseParent: condenseId }, + { ts: 999, role: "assistant", content: "Summary", isSummary: true, condenseId }, + { ts: 1000, role: "user", content: "First kept" }, + ] + + // Delete "Message 2" (ts=300) - this removes summary too, so orphaned tags should be cleared + await webviewMessageHandler(provider, { + type: "deleteMessageConfirm", + messageTs: 300, + }) + + expect(getCurrentTaskMock.overwriteApiConversationHistory).toHaveBeenCalled() + const result = getCurrentTaskMock.overwriteApiConversationHistory.mock.calls[0][0] + + // Summary was removed, so orphaned tags should be cleared + expect(result.length).toBe(2) + expect(result[0].content).toBe("Task start") + expect(result[1].content).toBe("Response 1") + expect(result[1].condenseParent).toBeUndefined() // Tag cleared since summary is gone + }) + + it("should preserve first condense but undo second when rewinding past second condense only", async () => { + // Scenario: Double condense, user deletes a message that removes the second summary + // but keeps the first summary. First condense should remain intact. + const condenseId1 = "summary-first" + const condenseId2 = "summary-second" + + getCurrentTaskMock.clineMessages = [ + { ts: 100, say: "user", text: "First message" }, + { ts: 799, say: "assistant", text: "Summary1" }, + { ts: 1799, say: "assistant", text: "Summary2" }, + { ts: 1800, say: "user", text: "Kept1" }, + { ts: 1900, say: "assistant", text: "Kept2" }, + { ts: 2000, say: "user", text: "To delete" }, + ] + + getCurrentTaskMock.apiConversationHistory = [ + { ts: 100, role: "user", content: "First message" }, + // Messages from first condense (tagged with condenseId1) + { ts: 200, role: "assistant", content: "Msg2", condenseParent: condenseId1 }, + { ts: 300, role: "user", content: "Msg3", condenseParent: condenseId1 }, + // First summary - ALSO tagged with condenseId2 from second condense + { + ts: 799, + role: "assistant", + content: "Summary1", + isSummary: true, + condenseId: condenseId1, + condenseParent: condenseId2, + }, + // Messages from second condense (tagged with condenseId2) + { ts: 1000, role: "assistant", content: "Msg after summary1", condenseParent: condenseId2 }, + { ts: 1100, role: "user", content: "More msgs", condenseParent: condenseId2 }, + // Second summary + { ts: 1799, role: "assistant", content: "Summary2", isSummary: true, condenseId: condenseId2 }, + // Kept messages + { ts: 1800, role: "user", content: "Kept1" }, + { ts: 1900, role: "assistant", content: "Kept2" }, + { ts: 2000, role: "user", content: "To delete" }, + ] + + // Delete "Kept2" (ts=1900) - summary2 is BEFORE truncation, so it's preserved + await webviewMessageHandler(provider, { + type: "deleteMessageConfirm", + messageTs: 1900, + }) + + expect(getCurrentTaskMock.overwriteApiConversationHistory).toHaveBeenCalled() + const result = getCurrentTaskMock.overwriteApiConversationHistory.mock.calls[0][0] + + // Both summaries should be preserved since they're before the truncation point + const summaries = result.filter((msg: any) => msg.isSummary) + expect(summaries.length).toBe(2) + + // Verify tags are preserved + const summary1 = result.find((msg: any) => msg.content === "Summary1") + expect(summary1.condenseParent).toBe(condenseId2) // Still tagged + }) + + it("should prefer non-summary message when timestamps collide for deletion target", async () => { + // When multiple messages share the same timestamp, prefer non-summary for targeting + const sharedTs = 1000 + + getCurrentTaskMock.clineMessages = [ + { ts: 900, say: "user", text: "Previous message" }, + { ts: sharedTs, say: "user", text: "First kept message" }, + { ts: 1100, say: "assistant", text: "Response" }, + ] + + // Summary and regular message share timestamp (edge case) + getCurrentTaskMock.apiConversationHistory = [ + { ts: 900, role: "user", content: "Previous message" }, + { ts: sharedTs, role: "assistant", content: "Summary", isSummary: true, condenseId: "abc" }, + { ts: sharedTs, role: "user", content: "First kept message" }, + { ts: 1100, role: "assistant", content: "Response" }, + ] + + // Delete at shared timestamp - should target non-summary message (index 2) + await webviewMessageHandler(provider, { + type: "deleteMessageConfirm", + messageTs: sharedTs, + }) + + expect(getCurrentTaskMock.overwriteApiConversationHistory).toHaveBeenCalled() + const result = getCurrentTaskMock.overwriteApiConversationHistory.mock.calls[0][0] + + // Truncation at index 2 means we keep indices 0-1: previous message and summary + expect(result.length).toBe(2) + expect(result[0].content).toBe("Previous message") + // The summary is kept since it's before truncation point + expect(result[1].content).toBe("Summary") + expect(result[1].isSummary).toBe(true) + }) + + it("should remove Summary when its condense_context clineMessage is deleted", async () => { + // Scenario: Summary has timestamp BEFORE the deletion point (so it survives truncation), + // BUT the condense_context UI message has timestamp AFTER the deletion point (so it gets removed). + // The fix links them via condenseId so the Summary is explicitly removed. + const condenseId = "summary-sync-test" + + getCurrentTaskMock.clineMessages = [ + { ts: 100, say: "user", text: "Task start" }, + { ts: 200, say: "assistant", text: "Response 1" }, + { ts: 300, say: "user", text: "Message to delete this and after" }, + { ts: 400, say: "assistant", text: "Response 2" }, + // condense_context is created AFTER the condense operation + { ts: 500, say: "condense_context", contextCondense: { condenseId, summary: "Summary text" } }, + { ts: 600, say: "user", text: "Post-condense message" }, + ] + + // Summary has ts=299 (before first kept message), so it would survive basic truncation + // But since condense_context (ts=500) is being removed, Summary should be removed too + getCurrentTaskMock.apiConversationHistory = [ + { ts: 100, role: "user", content: "Task start" }, + { ts: 200, role: "assistant", content: "Response 1", condenseParent: condenseId }, + // Summary timestamp is BEFORE the kept messages (this is the bug scenario) + { ts: 299, role: "assistant", content: "Summary text", isSummary: true, condenseId }, + { ts: 300, role: "user", content: "Message to delete this and after" }, + { ts: 400, role: "assistant", content: "Response 2" }, + { ts: 600, role: "user", content: "Post-condense message" }, + ] + + // Delete at ts=300 - this removes condense_context (ts=500), so Summary should be removed too + await webviewMessageHandler(provider, { + type: "deleteMessageConfirm", + messageTs: 300, + }) + + expect(getCurrentTaskMock.overwriteApiConversationHistory).toHaveBeenCalled() + const result = getCurrentTaskMock.overwriteApiConversationHistory.mock.calls[0][0] + + // Summary should be REMOVED even though its timestamp (299) is before truncation point (300) + // because its corresponding condense_context message is being removed + expect(result.length).toBe(2) + expect(result[0].content).toBe("Task start") + expect(result[1].content).toBe("Response 1") + // condenseParent should be cleared since the Summary is gone + expect(result[1].condenseParent).toBeUndefined() + }) + + it("should preserve first Summary when only second condense_context is deleted (nested condense)", async () => { + // Scenario: Two condense operations occurred. User deletes a message that removes + // the second condense_context but keeps the first. First summary should stay intact. + const condenseId1 = "summary-first" + const condenseId2 = "summary-second" + + getCurrentTaskMock.clineMessages = [ + { ts: 100, say: "user", text: "First message" }, + { ts: 200, say: "assistant", text: "Response 1" }, + // First condense_context created after first condense + { + ts: 800, + say: "condense_context", + contextCondense: { condenseId: condenseId1, summary: "First summary" }, + }, + { ts: 900, say: "user", text: "After first condense" }, + { ts: 1000, say: "assistant", text: "Response after 1st condense" }, + // Delete target - deleting this will remove the second condense_context below + { ts: 1100, say: "user", text: "Message to delete this and after" }, + // Second condense_context created after second condense (AFTER delete target) + { + ts: 1800, + say: "condense_context", + contextCondense: { condenseId: condenseId2, summary: "Second summary" }, + }, + { ts: 1900, say: "user", text: "Post second condense" }, + { ts: 2000, say: "assistant", text: "Final response" }, + ] + + getCurrentTaskMock.apiConversationHistory = [ + { ts: 100, role: "user", content: "First message" }, + // Messages from first condense (tagged with condenseId1) + { ts: 200, role: "assistant", content: "Response 1", condenseParent: condenseId1 }, + // First summary (also tagged with condenseId2 from second condense) + { + ts: 799, + role: "assistant", + content: "First summary", + isSummary: true, + condenseId: condenseId1, + condenseParent: condenseId2, + }, + { ts: 900, role: "user", content: "After first condense", condenseParent: condenseId2 }, + { + ts: 1000, + role: "assistant", + content: "Response after 1st condense", + condenseParent: condenseId2, + }, + { ts: 1100, role: "user", content: "Message to delete this and after" }, + // Second summary (timestamp is BEFORE the messages it summarized for sort purposes) + { + ts: 1799, + role: "assistant", + content: "Second summary", + isSummary: true, + condenseId: condenseId2, + }, + { ts: 1900, role: "user", content: "Post second condense" }, + { ts: 2000, role: "assistant", content: "Final response" }, + ] + + // Delete at ts=1100 - this removes second condense_context (ts=1800) but keeps first (ts=800) + await webviewMessageHandler(provider, { + type: "deleteMessageConfirm", + messageTs: 1100, + }) + + expect(getCurrentTaskMock.overwriteApiConversationHistory).toHaveBeenCalled() + const result = getCurrentTaskMock.overwriteApiConversationHistory.mock.calls[0][0] + + // First summary should be PRESERVED (its condense_context is not being removed) + const firstSummary = result.find((msg: any) => msg.condenseId === condenseId1) + expect(firstSummary).toBeDefined() + expect(firstSummary.content).toBe("First summary") + expect(firstSummary.isSummary).toBe(true) + + // Second summary should be REMOVED (its condense_context is being removed) + const secondSummary = result.find((msg: any) => msg.condenseId === condenseId2) + expect(secondSummary).toBeUndefined() + + // Messages that were tagged with condenseId2 should have their tags cleared + const afterFirstCondense = result.find((msg: any) => msg.content === "After first condense") + expect(afterFirstCondense?.condenseParent).toBeUndefined() // Tag cleared + + // Messages tagged with condenseId1 should KEEP their tags + const response1 = result.find((msg: any) => msg.content === "Response 1") + expect(response1?.condenseParent).toBe(condenseId1) // Tag preserved + }) + }) }) }) diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 6f2e18cd6f9..c530fa2bd75 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -22,6 +22,7 @@ import { TelemetryService } from "@roo-code/telemetry" import { type ApiMessage } from "../task-persistence/apiMessages" import { saveTaskMessages } from "../task-persistence" +import { cleanupAfterTruncation } from "../condense" import { ClineProvider } from "./ClineProvider" import { BrowserSessionPanelManager } from "./BrowserSessionPanelManager" @@ -93,14 +94,24 @@ export const webviewMessageHandler = async ( return provider.getCurrentTask()?.cwd || provider.cwd } /** - * Shared utility to find message indices based on timestamp + * Shared utility to find message indices based on timestamp. + * When multiple messages share the same timestamp (e.g., after condense), + * this function prefers non-summary messages to ensure user operations + * target the intended message rather than the summary. */ const findMessageIndices = (messageTs: number, currentCline: any) => { // Find the exact message by timestamp, not the first one after a cutoff const messageIndex = currentCline.clineMessages.findIndex((msg: ClineMessage) => msg.ts === messageTs) - const apiConversationHistoryIndex = currentCline.apiConversationHistory.findIndex( - (msg: ApiMessage) => msg.ts === messageTs, - ) + + // Find all matching API messages by timestamp + const allApiMatches = currentCline.apiConversationHistory + .map((msg: ApiMessage, idx: number) => ({ msg, idx })) + .filter(({ msg }: { msg: ApiMessage }) => msg.ts === messageTs) + + // Prefer non-summary message if multiple matches exist (handles timestamp collision after condense) + const preferred = allApiMatches.find(({ msg }: { msg: ApiMessage }) => !msg.isSummary) || allApiMatches[0] + const apiConversationHistoryIndex = preferred?.idx ?? -1 + return { messageIndex, apiConversationHistoryIndex } } @@ -116,20 +127,81 @@ export const webviewMessageHandler = async ( } /** - * Removes the target message and all subsequent messages + * Removes the target message and all subsequent messages. + * After truncation, cleans up orphaned condenseParent and truncationParent references for any + * summaries or truncation markers that were removed by the truncation. + * + * Design: Rewind/delete operations preserve earlier condense and truncation states. + * Only summaries and truncation markers that are removed by the truncation (i.e., were created + * after the rewind point) have their associated tags cleared. + * This allows nested condensing and multiple truncations to work correctly - rewinding past the + * second condense restores visibility of messages condensed by it, while keeping the first condense intact. + * Same applies to truncation markers. */ const removeMessagesThisAndSubsequent = async ( currentCline: any, messageIndex: number, apiConversationHistoryIndex: number, ) => { - // Delete this message and all that follow + // Step 1: Collect condenseIds from condense_context messages being removed. + // These IDs link clineMessages to their corresponding Summaries in apiConversationHistory. + const removedCondenseIds = new Set() + // Step 1b: Collect truncationIds from sliding_window_truncation messages being removed. + // These IDs link clineMessages to their corresponding truncation markers in apiConversationHistory. + const removedTruncationIds = new Set() + + for (let i = messageIndex; i < currentCline.clineMessages.length; i++) { + const msg = currentCline.clineMessages[i] + if (msg.say === "condense_context" && msg.contextCondense?.condenseId) { + removedCondenseIds.add(msg.contextCondense.condenseId) + } + if (msg.say === "sliding_window_truncation" && msg.contextTruncation?.truncationId) { + removedTruncationIds.add(msg.contextTruncation.truncationId) + } + } + + // Step 2: Delete this message and all that follow await currentCline.overwriteClineMessages(currentCline.clineMessages.slice(0, messageIndex)) if (apiConversationHistoryIndex !== -1) { - await currentCline.overwriteApiConversationHistory( - currentCline.apiConversationHistory.slice(0, apiConversationHistoryIndex), - ) + // Step 3: Truncate API history by timestamp/index + let truncatedApiHistory = currentCline.apiConversationHistory.slice(0, apiConversationHistoryIndex) + + // Step 4: Remove Summaries whose condenseId was in a removed condense_context message. + // This handles the case where Summary.ts < truncation point but condense_context.ts > truncation point. + // Without this, the Summary would survive truncation but its corresponding UI event would be gone. + if (removedCondenseIds.size > 0) { + truncatedApiHistory = truncatedApiHistory.filter((msg: ApiMessage) => { + if (msg.isSummary && msg.condenseId && removedCondenseIds.has(msg.condenseId)) { + console.log( + `[removeMessagesThisAndSubsequent] Removing orphaned Summary with condenseId=${msg.condenseId}`, + ) + return false + } + return true + }) + } + + // Step 4b: Remove truncation markers whose truncationId was in a removed sliding_window_truncation message. + // Same logic as condense - without this, the marker would survive but its UI event would be gone. + if (removedTruncationIds.size > 0) { + truncatedApiHistory = truncatedApiHistory.filter((msg: ApiMessage) => { + if (msg.isTruncationMarker && msg.truncationId && removedTruncationIds.has(msg.truncationId)) { + console.log( + `[removeMessagesThisAndSubsequent] Removing orphaned truncation marker with truncationId=${msg.truncationId}`, + ) + return false + } + return true + }) + } + + // Step 5: Clean up orphaned condenseParent and truncationParent references for messages whose + // summary or truncation marker was removed by the truncation. Summaries, truncation markers, and messages + // from earlier condense/truncation operations are preserved. + const cleanedApiHistory = cleanupAfterTruncation(truncatedApiHistory) + + await currentCline.overwriteApiConversationHistory(cleanedApiHistory) } } diff --git a/src/integrations/editor/__tests__/detect-omission.spec.ts b/src/integrations/editor/__tests__/detect-omission.spec.ts deleted file mode 100644 index 6ff31c390a5..00000000000 --- a/src/integrations/editor/__tests__/detect-omission.spec.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { detectCodeOmission } from "../detect-omission" - -describe("detectCodeOmission", () => { - const originalContent = `function example() { - // Some code - const x = 1; - const y = 2; - return x + y; -}` - - // Generate content with a specified number of lines (100+ lines triggers detection) - const generateLongContent = (commentLine: string, length: number = 110) => { - return `${commentLine} - ${Array.from({ length }, (_, i) => `const x${i} = ${i};`).join("\n")} - const y = 2;` - } - - it("should skip comment checks for files under 100 lines", () => { - const newContent = `// Lines 1-50 remain unchanged -const z = 3;` - expect(detectCodeOmission(originalContent, newContent)).toBe(false) - }) - - it("should not detect regular comments without omission keywords", () => { - const newContent = generateLongContent("// Adding new functionality") - expect(detectCodeOmission(originalContent, newContent)).toBe(false) - }) - - it("should not detect when comment is part of original content", () => { - const originalWithComment = `// Content remains unchanged -${originalContent}` - const newContent = generateLongContent("// Content remains unchanged") - expect(detectCodeOmission(originalWithComment, newContent)).toBe(false) - }) - - it("should not detect code that happens to contain omission keywords", () => { - const newContent = generateLongContent(`const remains = 'some value'; -const unchanged = true;`) - expect(detectCodeOmission(originalContent, newContent)).toBe(false) - }) - - it("should detect suspicious single-line comment for files with 100+ lines", () => { - const newContent = generateLongContent("// Previous content remains here\nconst x = 1;") - expect(detectCodeOmission(originalContent, newContent)).toBe(true) - }) - - it("should detect suspicious Python-style comment for files with 100+ lines", () => { - const newContent = generateLongContent("# Previous content remains here\nconst x = 1;") - expect(detectCodeOmission(originalContent, newContent)).toBe(true) - }) - - it("should detect suspicious multi-line comment for files with 100+ lines", () => { - const newContent = generateLongContent("/* Previous content remains the same */\nconst x = 1;") - expect(detectCodeOmission(originalContent, newContent)).toBe(true) - }) - - it("should detect suspicious JSX comment for files with 100+ lines", () => { - const newContent = generateLongContent("{/* Rest of the code remains the same */}\nconst x = 1;") - expect(detectCodeOmission(originalContent, newContent)).toBe(true) - }) - - it("should detect suspicious HTML comment for files with 100+ lines", () => { - const newContent = generateLongContent("\nconst x = 1;") - expect(detectCodeOmission(originalContent, newContent)).toBe(true) - }) - - it("should detect suspicious square bracket notation for files with 100+ lines", () => { - const newContent = generateLongContent( - "[Previous content from line 1-305 remains exactly the same]\nconst x = 1;", - ) - expect(detectCodeOmission(originalContent, newContent)).toBe(true) - }) - - it("should not flag legitimate comments in files with 100+ lines when in original", () => { - const originalWithComment = `// This is a legitimate comment that remains here -${originalContent}` - const newContent = generateLongContent("// This is a legitimate comment that remains here") - expect(detectCodeOmission(originalWithComment, newContent)).toBe(false) - }) -}) diff --git a/src/integrations/editor/detect-omission.ts b/src/integrations/editor/detect-omission.ts deleted file mode 100644 index d55acd4183c..00000000000 --- a/src/integrations/editor/detect-omission.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Detects potential AI-generated code omissions in the given file content. - * Looks for comments containing omission keywords that weren't in the original file. - * @param originalFileContent The original content of the file. - * @param newFileContent The new content of the file to check. - * @returns True if a potential omission is detected, false otherwise. - */ -export function detectCodeOmission(originalFileContent: string, newFileContent: string): boolean { - const actualLineCount = newFileContent.split("\n").length - - // Skip checks for small files (less than 100 lines) - if (actualLineCount < 100) { - return false - } - - const originalLines = originalFileContent.split("\n") - const newLines = newFileContent.split("\n") - const omissionKeywords = [ - "remain", - "remains", - "unchanged", - "rest", - "previous", - "existing", - "content", - "same", - "...", - ] - - const commentPatterns = [ - /^\s*\/\//, // Single-line comment for most languages - /^\s*#/, // Single-line comment for Python, Ruby, etc. - /^\s*\/\*/, // Multi-line comment opening - /^\s*{\s*\/\*/, // JSX comment opening - /^\s*