diff --git a/.changeset/convert-to-zod.md b/.changeset/convert-to-zod.md new file mode 100644 index 0000000..bea2cbf --- /dev/null +++ b/.changeset/convert-to-zod.md @@ -0,0 +1,6 @@ +--- +'mycoder-agent': minor +'mycoder': minor +--- + +Convert from JsonSchema7Type to ZodSchema for tool parameters and returns, required for Vercel AI SDK integration. diff --git a/.changeset/implement-token-caching.md b/.changeset/implement-token-caching.md new file mode 100644 index 0000000..6c1c577 --- /dev/null +++ b/.changeset/implement-token-caching.md @@ -0,0 +1,5 @@ +--- +"mycoder-agent": patch +--- + +Re-implemented token caching for Vercel AI SDK usage with Anthropic provider to reduce token consumption during repeated API calls. \ No newline at end of file diff --git a/docs/LargeCodeBase_Plan.md b/docs/LargeCodeBase_Plan.md index 52a7781..b9ecb13 100644 --- a/docs/LargeCodeBase_Plan.md +++ b/docs/LargeCodeBase_Plan.md @@ -11,16 +11,19 @@ This document presents research findings on how leading AI coding tools handle l While detailed technical documentation on Claude Code's internal architecture is limited in public sources, we can infer several approaches from Anthropic's general AI architecture and Claude Code's capabilities: 1. **Chunking and Retrieval Augmentation**: + - Claude Code likely employs retrieval-augmented generation (RAG) to handle large codebases - Files are likely chunked into manageable segments with semantic understanding - Relevant code chunks are retrieved based on query relevance 2. **Hierarchical Code Understanding**: + - Builds a hierarchical representation of code (project → modules → files → functions) - Maintains a graph of relationships between code components - Prioritizes context based on relevance to the current task 3. **Incremental Context Management**: + - Dynamically adjusts the context window to include only relevant code - Maintains a "working memory" of recently accessed or modified files - Uses sliding context windows to process large files sequentially @@ -35,16 +38,19 @@ While detailed technical documentation on Claude Code's internal architecture is Aider's approach to handling large codebases can be inferred from its open-source codebase and documentation: 1. **Git Integration**: + - Leverages Git to track file changes and understand repository structure - Uses Git history to prioritize recently modified files - Employs Git's diff capabilities to minimize context needed for changes 2. **Selective File Context**: + - Only includes relevant files in the context rather than the entire codebase - Uses heuristics to identify related files based on imports, references, and naming patterns - Implements a "map-reduce" approach where it first analyzes the codebase structure, then selectively processes relevant files 3. **Prompt Engineering and Chunking**: + - Designs prompts that can work with limited context by focusing on specific tasks - Chunks large files and processes them incrementally - Uses summarization to compress information about non-focal code parts @@ -90,6 +96,7 @@ Based on the research findings, we recommend the following enhancements to MyCod ``` **Implementation Details:** + - Create a lightweight indexer that runs during project initialization - Generate embeddings for code files, focusing on API definitions, function signatures, and documentation - Build a graph of relationships between files based on imports/exports and references @@ -120,6 +127,7 @@ Based on the research findings, we recommend the following enhancements to MyCod ``` **Implementation Details:** + - Develop a working set manager that tracks currently relevant files - Implement a relevance scoring algorithm that considers: - Semantic similarity to the current task @@ -148,6 +156,7 @@ Based on the research findings, we recommend the following enhancements to MyCod ``` **Implementation Details:** + - Chunk files at meaningful boundaries (functions, classes, modules) - Implement overlapping chunks to maintain context across boundaries - Develop a progressive loading strategy: @@ -181,6 +190,7 @@ Based on the research findings, we recommend the following enhancements to MyCod ``` **Implementation Details:** + - Implement a multi-level caching system: - Token cache: Store tokenized representations of files to avoid re-tokenization - Embedding cache: Store vector embeddings for semantic search @@ -209,6 +219,7 @@ Based on the research findings, we recommend the following enhancements to MyCod ``` **Implementation Details:** + - Improve task decomposition to identify parallelizable sub-tasks - Implement smart context distribution to sub-agents: - Provide each sub-agent with only the context it needs @@ -222,16 +233,19 @@ Based on the research findings, we recommend the following enhancements to MyCod ## Implementation Roadmap ### Phase 1: Foundation (1-2 months) + - Develop the basic indexing system for project structure and file metadata - Implement a simple relevance-based context selection mechanism - Create a basic chunking strategy for large files ### Phase 2: Advanced Features (2-3 months) + - Implement the semantic indexing system with code embeddings - Develop the full context management system with working sets - Create the multi-level caching system ### Phase 3: Optimization and Integration (1-2 months) + - Enhance sub-agent coordination for parallel processing - Optimize performance with better caching and context management - Integrate all components into a cohesive system diff --git a/docs/SentryIntegration.md b/docs/SentryIntegration.md index b6897f2..8ab2745 100644 --- a/docs/SentryIntegration.md +++ b/docs/SentryIntegration.md @@ -17,6 +17,7 @@ npm install @sentry/node --save ## Configuration By default, Sentry is: + - Enabled in production environments - Disabled in development environments (unless explicitly enabled) - Configured to capture 100% of transactions @@ -56,7 +57,9 @@ Sentry.init({ tracesSampleRate: 1.0, environment: process.env.NODE_ENV || 'development', release: `mycoder@${packageVersion}`, - enabled: process.env.NODE_ENV !== 'development' || process.env.ENABLE_SENTRY === 'true', + enabled: + process.env.NODE_ENV !== 'development' || + process.env.ENABLE_SENTRY === 'true', }); // Capture errors @@ -76,6 +79,7 @@ mycoder test-sentry ``` This command will: + 1. Generate a test error that includes the package version 2. Report it to Sentry.io 3. Output the result to the console @@ -85,6 +89,7 @@ Note: In development environments, you may need to set `ENABLE_SENTRY=true` for ## Privacy Error reports sent to Sentry include: + - Stack traces - Error messages - Environment information diff --git a/packages/agent/package.json b/packages/agent/package.json index 6126113..c2c5578 100644 --- a/packages/agent/package.json +++ b/packages/agent/package.json @@ -44,13 +44,16 @@ "author": "Ben Houston", "license": "MIT", "dependencies": { - "@anthropic-ai/sdk": "^0.37", + "@ai-sdk/anthropic": "^1.1.13", + "@ai-sdk/openai": "^1.2.0", "@mozilla/readability": "^0.5.0", "@playwright/test": "^1.50.1", "@vitest/browser": "^3.0.5", + "ai": "^4.1.50", "chalk": "^5", "dotenv": "^16", "jsdom": "^26.0.0", + "ollama-ai-provider": "^1.2.0", "playwright": "^1.50.1", "uuid": "^11", "zod": "^3", diff --git a/packages/agent/src/core/tokens.ts b/packages/agent/src/core/tokens.ts index e1d99da..ebad962 100644 --- a/packages/agent/src/core/tokens.ts +++ b/packages/agent/src/core/tokens.ts @@ -1,4 +1,4 @@ -import Anthropic from '@anthropic-ai/sdk'; +//import Anthropic from '@anthropic-ai/sdk'; import { LogLevel } from '../utils/logger.js'; @@ -34,6 +34,7 @@ export class TokenUsage { return usage; } + /* static fromMessage(message: Anthropic.Message) { const usage = new TokenUsage(); usage.input = message.usage.input_tokens; @@ -41,7 +42,7 @@ export class TokenUsage { usage.cacheReads = message.usage.cache_read_input_tokens ?? 0; usage.output = message.usage.output_tokens; return usage; - } + }*/ static sum(usages: TokenUsage[]) { const usage = new TokenUsage(); diff --git a/packages/agent/src/core/toolAgent.respawn.test.ts b/packages/agent/src/core/toolAgent.respawn.test.ts index be5c49a..40046d9 100644 --- a/packages/agent/src/core/toolAgent.respawn.test.ts +++ b/packages/agent/src/core/toolAgent.respawn.test.ts @@ -1,3 +1,4 @@ +import { anthropic } from '@ai-sdk/anthropic'; import { describe, it, expect, vi, beforeEach } from 'vitest'; import { toolAgent } from '../../src/core/toolAgent.js'; @@ -15,32 +16,6 @@ const toolContext: ToolContext = { pageFilter: 'simple', tokenTracker: new TokenTracker(), }; -// Mock Anthropic SDK -vi.mock('@anthropic-ai/sdk', () => { - return { - default: vi.fn().mockImplementation(() => ({ - messages: { - create: vi - .fn() - .mockResolvedValueOnce({ - content: [ - { - type: 'tool_use', - name: 'respawn', - id: 'test-id', - input: { respawnContext: 'new context' }, - }, - ], - usage: { input_tokens: 10, output_tokens: 10 }, - }) - .mockResolvedValueOnce({ - content: [], - usage: { input_tokens: 5, output_tokens: 5 }, - }), - }, - })), - }; -}); describe('toolAgent respawn functionality', () => { const tools = getTools(); @@ -56,7 +31,7 @@ describe('toolAgent respawn functionality', () => { tools, { maxIterations: 2, // Need at least 2 iterations for respawn + empty response - model: 'test-model', + model: anthropic('claude-3-7-sonnet-20250219'), maxTokens: 100, temperature: 0, getSystemPrompt: () => 'test system prompt', diff --git a/packages/agent/src/core/toolAgent.test.ts b/packages/agent/src/core/toolAgent.test.ts index 43bf116..dc63da0 100644 --- a/packages/agent/src/core/toolAgent.test.ts +++ b/packages/agent/src/core/toolAgent.test.ts @@ -1,4 +1,6 @@ +import { anthropic } from '@ai-sdk/anthropic'; import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import { z } from 'zod'; import { MockLogger } from '../utils/mockLogger.js'; @@ -19,7 +21,7 @@ const toolContext: ToolContext = { // Mock configuration for testing const testConfig = { maxIterations: 50, - model: 'claude-3-7-sonnet-latest', + model: anthropic('claude-3-7-sonnet-20250219'), maxTokens: 4096, temperature: 0.7, getSystemPrompt: () => 'Test system prompt', @@ -64,7 +66,11 @@ describe('toolAgent', () => { const mockTool: Tool = { name: 'mockTool', description: 'A mock tool for testing', - parameters: { + parameters: z.object({ + input: z.string().describe('Test input'), + }), + returns: z.string().describe('The processed result'), + parametersJsonSchema: { type: 'object', properties: { input: { @@ -74,7 +80,7 @@ describe('toolAgent', () => { }, required: ['input'], }, - returns: { + returnsJsonSchema: { type: 'string', description: 'The processed result', }, @@ -84,7 +90,11 @@ describe('toolAgent', () => { const sequenceCompleteTool: Tool = { name: 'sequenceComplete', description: 'Completes the sequence', - parameters: { + parameters: z.object({ + result: z.string().describe('The final result'), + }), + returns: z.string().describe('The final result'), + parametersJsonSchema: { type: 'object', properties: { result: { @@ -94,7 +104,7 @@ describe('toolAgent', () => { }, required: ['result'], }, - returns: { + returnsJsonSchema: { type: 'string', description: 'The final result', }, @@ -133,12 +143,14 @@ describe('toolAgent', () => { const errorTool: Tool = { name: 'errorTool', description: 'A tool that always fails', - parameters: { + parameters: z.object({}), + returns: z.string().describe('Error message'), + parametersJsonSchema: { type: 'object', properties: {}, required: [], }, - returns: { + returnsJsonSchema: { type: 'string', description: 'Error message', }, diff --git a/packages/agent/src/core/toolAgent.ts b/packages/agent/src/core/toolAgent.ts index 4a7c9ae..9c7b146 100644 --- a/packages/agent/src/core/toolAgent.ts +++ b/packages/agent/src/core/toolAgent.ts @@ -1,19 +1,25 @@ import { execSync } from 'child_process'; -import Anthropic from '@anthropic-ai/sdk'; -import { ContentBlockParam } from '@anthropic-ai/sdk/resources/messages/messages.js'; +import { anthropic } from '@ai-sdk/anthropic'; +import { + CoreMessage, + CoreToolMessage, + generateText, + ToolResultPart, + ToolSet, + tool as makeTool, + ToolCallPart, +} from 'ai'; import chalk from 'chalk'; import { getAnthropicApiKeyError } from '../utils/errors.js'; import { executeToolCall } from './executeToolCall.js'; -import { TokenTracker, TokenUsage } from './tokens.js'; +import { TokenTracker } from './tokens.js'; import { Tool, - TextContent, ToolUseContent, ToolResultContent, - Message, ToolContext, } from './types.js'; @@ -24,7 +30,7 @@ export interface ToolAgentResult { const CONFIG = { maxIterations: 200, - model: 'claude-3-7-sonnet-latest', + model: anthropic('claude-3-7-sonnet-20250219'), maxTokens: 4096, temperature: 0.7, getSystemPrompt: () => { @@ -86,9 +92,9 @@ const CONFIG = { interface ToolCallResult { sequenceCompleted: boolean; completionResult?: string; - toolResults: ToolResultContent[]; + toolResults: ToolResultPart[]; } - +/* function processResponse(response: Anthropic.Message) { const content: (TextContent | ToolUseContent)[] = []; const toolCalls: ToolUseContent[] = []; @@ -110,11 +116,17 @@ function processResponse(response: Anthropic.Message) { return { content, toolCalls }; } +*/ + +type ErrorResult = { + errorMessage: string; + errorType: string; +}; async function executeTools( toolCalls: ToolUseContent[], tools: Tool[], - messages: Message[], + messages: CoreMessage[], context: ToolContext, ): Promise { if (toolCalls.length === 0) { @@ -132,10 +144,11 @@ async function executeTools( sequenceCompleted: false, toolResults: [ { - type: 'tool_result', - tool_use_id: respawnCall.id, - content: 'Respawn initiated', - }, + type: 'tool-result', + toolCallId: respawnCall.id, + toolName: respawnCall.name, + result: { success: true }, + } satisfies ToolResultPart, ], respawn: { context: respawnCall.input.respawnContext, @@ -143,7 +156,7 @@ async function executeTools( }; } - const results = await Promise.all( + const toolResults: ToolResultPart[] = await Promise.all( toolCalls.map(async (call) => { let toolResult = ''; try { @@ -152,92 +165,85 @@ async function executeTools( tokenTracker: new TokenTracker(call.name, context.tokenTracker), }); } catch (error: any) { - toolResult = `Error: Exception thrown during tool execution. Type: ${error.constructor.name}, Message: ${error.message}`; + toolResult = JSON.stringify({ + errorMessage: error.message, + errorType: error.constructor.name, + }); } + return { - type: 'tool_result' as const, - tool_use_id: call.id, - content: toolResult, - isComplete: call.name === 'sequenceComplete', - }; + type: 'tool-result', + toolCallId: call.id, + toolName: call.name, + result: JSON.parse(toolResult) satisfies ToolResultContent, + } satisfies ToolResultPart; }), ); - const toolResults = results.map(({ type, tool_use_id, content }) => ({ - type, - tool_use_id, - content, - })); - - const sequenceCompleted = results.some((r) => r.isComplete); - const completionResult = results.find((r) => r.isComplete)?.content; + const sequenceCompletedTool = toolResults.find( + (r) => r.toolName === 'sequenceComplete', + ); + const completionResult = (sequenceCompletedTool?.result as { result: string }) + .result; messages.push({ - role: 'user', + role: 'tool', content: toolResults, - }); + } satisfies CoreToolMessage); - if (sequenceCompleted) { + if (sequenceCompletedTool) { logger.verbose('Sequence completed', { completionResult }); } - return { sequenceCompleted, completionResult, toolResults }; + return { + sequenceCompleted: sequenceCompletedTool !== undefined, + completionResult, + toolResults, + }; } -// a function that takes a list of messages and returns a list of messages but with the last message having a cache_control of ephemeral -function addCacheControlToTools(messages: T[]): T[] { - return messages.map((m, i) => ({ - ...m, - ...(i === messages.length - 1 - ? { cache_control: { type: 'ephemeral' } } - : {}), - })); +function createCacheControlMessageFromSystemPrompt( + systemPrompt: string, +): CoreMessage { + return { + role: 'system', + content: systemPrompt, + providerOptions: { + anthropic: { cacheControl: { type: 'ephemeral' } }, + }, + }; } -function addCacheControlToContentBlocks( - content: ContentBlockParam[], -): ContentBlockParam[] { - return content.map((c, i) => { - if (i === content.length - 1) { - if ( - c.type === 'text' || - c.type === 'document' || - c.type === 'image' || - c.type === 'tool_use' || - c.type === 'tool_result' || - c.type === 'thinking' || - c.type === 'redacted_thinking' - ) { - return { ...c, cache_control: { type: 'ephemeral' } }; +/** + * Adds cache control to the messages for token caching with the Vercel AI SDK + * This marks the last two messages as ephemeral which allows the conversation up to that + * point to be cached (with a ~5 minute window), reducing token usage when making multiple API calls + */ +function addCacheControlToMessages(messages: CoreMessage[]): CoreMessage[] { + if (messages.length <= 1) return messages; + + // Create a deep copy of the messages array to avoid mutating the original + const result = JSON.parse(JSON.stringify(messages)) as CoreMessage[]; + + // Get the last two messages (if available) + const lastTwoMessageIndices = [messages.length - 1, messages.length - 2]; + + // Add providerOptions with anthropic cache control to the last two messages + lastTwoMessageIndices.forEach((index) => { + if (index >= 0) { + const message = result[index]; + if (message) { + // For the Vercel AI SDK, we need to add the providerOptions.anthropic property + // with cacheControl: 'ephemeral' to enable token caching + message.providerOptions = { + ...message.providerOptions, + anthropic: { cacheControl: { type: 'ephemeral' } }, + }; } } - return c; - }); -} -function addCacheControlToMessages( - messages: Anthropic.Messages.MessageParam[], -): Anthropic.Messages.MessageParam[] { - return messages.map((m, i) => { - if (typeof m.content === 'string') { - return { - ...m, - content: [ - { - type: 'text', - text: m.content, - cache_control: { type: 'ephemeral' }, - }, - ] as ContentBlockParam[], - }; - } - return { - ...m, - content: - i >= messages.length - 2 - ? addCacheControlToContentBlocks(m.content) - : m.content, - }; }); + + return result; } export const toolAgent = async ( @@ -256,8 +262,8 @@ export const toolAgent = async ( const apiKey = process.env.ANTHROPIC_API_KEY; if (!apiKey) throw new Error(getAnthropicApiKeyError()); - const client = new Anthropic({ apiKey }); - const messages: Message[] = [ + // const client = new Anthropic({ apiKey }); + const messages: CoreMessage[] = [ { role: 'user', content: [{ type: 'text', text: initialPrompt }], @@ -278,32 +284,41 @@ export const toolAgent = async ( interactions++; - // Create request parameters - const requestParams: Anthropic.MessageCreateParams = { + const toolSet: ToolSet = {}; + tools.forEach((tool) => { + toolSet[tool.name] = makeTool({ + description: tool.description, + parameters: tool.parameters, + }); + }); + // Apply cache control to messages for token caching + const messagesWithCacheControl = [ + createCacheControlMessageFromSystemPrompt(systemPrompt), + ...addCacheControlToMessages(messages), + ]; + + const generateTextProps = { model: config.model, - max_tokens: config.maxTokens, temperature: config.temperature, - messages: addCacheControlToMessages(messages), - system: [ - { - type: 'text', - text: systemPrompt, - cache_control: { type: 'ephemeral' }, - }, - ], - tools: addCacheControlToTools( - tools.map((t) => ({ - name: t.name, - description: t.description, - input_schema: t.parameters as Anthropic.Tool.InputSchema, - })), - ), - tool_choice: { type: 'auto' }, + messages: messagesWithCacheControl, + tools: toolSet, }; - - const response = await client.messages.create(requestParams); - - if (!response.content.length) { + const { text, toolCalls, ...other } = await generateText(generateTextProps); + + //console.log( + // 'providerMetadata', + // JSON.stringify(other.providerMetadata, null, 2), + //); + //console.log('other data', JSON.stringify(other, null, 2)); + + const localToolCalls: ToolUseContent[] = toolCalls.map((call) => ({ + type: 'tool_use', + name: call.toolName, + id: call.toolCallId, + input: call.args, + })); + + if (!text.length) { // Instead of treating empty response as completion, remind the agent logger.verbose('Received empty response from agent, sending reminder'); messages.push({ @@ -319,31 +334,39 @@ export const toolAgent = async ( } // Track both regular and cached token usage - const tokenUsagePerMessage = TokenUsage.fromMessage(response); - tokenTracker.tokenUsage.add(tokenUsagePerMessage); + //const tokenUsagePerMessage = TokenUsage.fromMessage(response); + //tokenTracker.tokenUsage.add(tokenUsagePerMessage); - const { content, toolCalls } = processResponse(response); messages.push({ role: 'assistant', - content, + content: [{ type: 'text', text: text }], }); - // Log the assistant's message - const assistantMessage = content - .filter((c) => c.type === 'text') - .map((c) => c.text) - .join('\\n'); - if (assistantMessage) { - logger.info(assistantMessage); + if (text) { + logger.info(text); } - logger.log( + if (toolCalls.length > 0) { + const toolCallParts: Array = toolCalls.map((toolCall) => ({ + type: 'tool-call', + toolCallId: toolCall.toolCallId, + toolName: toolCall.toolName, + args: toolCall.args, + })); + + messages.push({ + role: 'assistant', + content: toolCallParts, + }); + } + + /*logger.log( tokenTracker.logLevel, chalk.blue(`[Token Usage/Message] ${tokenUsagePerMessage.toString()}`), - ); + );*/ const { sequenceCompleted, completionResult, respawn } = await executeTools( - toolCalls, + localToolCalls, tools, messages, context, @@ -361,10 +384,8 @@ export const toolAgent = async ( } if (sequenceCompleted) { - const result = { - result: - completionResult ?? - 'Sequence explicitly completed with an empty result', + const result: ToolAgentResult = { + result: completionResult ?? 'Sequence explicitly completed', interactions, }; logger.log( diff --git a/packages/agent/src/core/types.ts b/packages/agent/src/core/types.ts index 328f146..1bdab20 100644 --- a/packages/agent/src/core/types.ts +++ b/packages/agent/src/core/types.ts @@ -1,3 +1,4 @@ +import { z } from 'zod'; import { JsonSchema7Type } from 'zod-to-json-schema'; import { Logger } from '../utils/logger.js'; @@ -20,14 +21,18 @@ export type ToolContext = { export type Tool, TReturn = any> = { name: string; description: string; - parameters: JsonSchema7Type; - returns: JsonSchema7Type; + parameters: z.ZodType; + returns: z.ZodType; logPrefix?: string; logParameters?: (params: TParams, context: ToolContext) => void; logReturns?: (returns: TReturn, context: ToolContext) => void; execute: (params: TParams, context: ToolContext) => Promise; + + // Keep JsonSchema7Type for backward compatibility and Vercel AI SDK integration + parametersJsonSchema?: JsonSchema7Type; + returnsJsonSchema?: JsonSchema7Type; }; export type ToolCall = { diff --git a/packages/agent/src/tools/browser/BrowserManager.ts b/packages/agent/src/tools/browser/BrowserManager.ts index c507666..a136e8a 100644 --- a/packages/agent/src/tools/browser/BrowserManager.ts +++ b/packages/agent/src/tools/browser/BrowserManager.ts @@ -18,7 +18,6 @@ export class BrowserManager { async createSession(config?: BrowserConfig): Promise { try { const sessionConfig = { ...this.defaultConfig, ...config }; - //console.log('sessionConfig', sessionConfig); const browser = await chromium.launch({ headless: sessionConfig.headless, }); diff --git a/packages/agent/src/tools/browser/browseMessage.ts b/packages/agent/src/tools/browser/browseMessage.ts index 49547da..9b9e299 100644 --- a/packages/agent/src/tools/browser/browseMessage.ts +++ b/packages/agent/src/tools/browser/browseMessage.ts @@ -70,8 +70,10 @@ export const browseMessageTool: Tool = { name: 'browseMessage', logPrefix: '🏄', description: 'Performs actions in an active browser session', - parameters: zodToJsonSchema(parameterSchema), - returns: zodToJsonSchema(returnSchema), + parameters: parameterSchema, + parametersJsonSchema: zodToJsonSchema(parameterSchema), + returns: returnSchema, + returnsJsonSchema: zodToJsonSchema(returnSchema), execute: async ( { instanceId, action }, diff --git a/packages/agent/src/tools/browser/browseStart.ts b/packages/agent/src/tools/browser/browseStart.ts index a4c5fa6..ebab30b 100644 --- a/packages/agent/src/tools/browser/browseStart.ts +++ b/packages/agent/src/tools/browser/browseStart.ts @@ -36,8 +36,10 @@ export const browseStartTool: Tool = { name: 'browseStart', logPrefix: '🏄', description: 'Starts a new browser session with optional initial URL', - parameters: zodToJsonSchema(parameterSchema), - returns: zodToJsonSchema(returnSchema), + parameters: parameterSchema, + parametersJsonSchema: zodToJsonSchema(parameterSchema), + returns: returnSchema, + returnsJsonSchema: zodToJsonSchema(returnSchema), execute: async ( { url, timeout = 30000 }, diff --git a/packages/agent/src/tools/browser/filterPageContent.ts b/packages/agent/src/tools/browser/filterPageContent.ts index a1d3879..398cc1e 100644 --- a/packages/agent/src/tools/browser/filterPageContent.ts +++ b/packages/agent/src/tools/browser/filterPageContent.ts @@ -80,13 +80,6 @@ async function getSimpleProcessedDOM(page: Page): Promise { elementsToRemove.forEach((element) => element.remove()); - console.log( - 'removing ', - elementsToRemove.length, - ' elements out of a total ', - elements.length, - ); - return clone.outerHTML; }); diff --git a/packages/agent/src/tools/interaction/subAgent.ts b/packages/agent/src/tools/interaction/subAgent.ts index 18f8715..8d8de08 100644 --- a/packages/agent/src/tools/interaction/subAgent.ts +++ b/packages/agent/src/tools/interaction/subAgent.ts @@ -1,3 +1,4 @@ +import { anthropic } from '@ai-sdk/anthropic'; import { z } from 'zod'; import { zodToJsonSchema } from 'zod-to-json-schema'; @@ -35,11 +36,13 @@ const parameterSchema = z.object({ .optional(), }); -const returnSchema = z - .string() - .describe( - 'The response from the sub-agent including its reasoning and tool usage', - ); +const returnSchema = z.object({ + response: z + .string() + .describe( + 'The response from the sub-agent including its reasoning and tool usage', + ), +}); type Parameters = z.infer; type ReturnType = z.infer; @@ -47,7 +50,7 @@ type ReturnType = z.infer; // Sub-agent specific configuration const subAgentConfig = { maxIterations: 50, - model: process.env.AGENT_MODEL || 'claude-3-opus-20240229', + model: anthropic('claude-3-7-sonnet-20250219'), maxTokens: 4096, temperature: 0.7, getSystemPrompt: () => { @@ -66,8 +69,10 @@ export const subAgentTool: Tool = { description: 'Creates a sub-agent that has access to all tools to solve a specific task', logPrefix: '🤖', - parameters: zodToJsonSchema(parameterSchema), - returns: zodToJsonSchema(returnSchema), + parameters: parameterSchema, + parametersJsonSchema: zodToJsonSchema(parameterSchema), + returns: returnSchema, + returnsJsonSchema: zodToJsonSchema(returnSchema), execute: async (params, context) => { // Validate parameters const { description, goal, projectContext, fileContext } = @@ -106,7 +111,7 @@ export const subAgentTool: Tool = { workingDirectory: fileContext?.workingDirectory ?? context.workingDirectory, }); - return result.result; // Return the result string directly + return { response: result.result }; }, logParameters: (input, { logger }) => { logger.info(`Delegating task "${input.description}"`); diff --git a/packages/agent/src/tools/interaction/userPrompt.ts b/packages/agent/src/tools/interaction/userPrompt.ts index ebeaa14..638085e 100644 --- a/packages/agent/src/tools/interaction/userPrompt.ts +++ b/packages/agent/src/tools/interaction/userPrompt.ts @@ -8,7 +8,9 @@ const parameterSchema = z.object({ prompt: z.string().describe('The prompt message to display to the user'), }); -const returnSchema = z.string().describe("The user's response"); +const returnSchema = z.object({ + userText: z.string().describe("The user's response"), +}); type Parameters = z.infer; type ReturnType = z.infer; @@ -17,8 +19,10 @@ export const userPromptTool: Tool = { name: 'userPrompt', description: 'Prompts the user for input and returns their response', logPrefix: '🗣️', - parameters: zodToJsonSchema(parameterSchema), - returns: zodToJsonSchema(returnSchema), + parameters: parameterSchema, + parametersJsonSchema: zodToJsonSchema(parameterSchema), + returns: returnSchema, + returnsJsonSchema: zodToJsonSchema(returnSchema), execute: async ({ prompt }, { logger }) => { logger.verbose(`Prompting user with: ${prompt}`); @@ -26,7 +30,7 @@ export const userPromptTool: Tool = { logger.verbose(`Received user response: ${response}`); - return response; + return { userText: response }; }, logParameters: () => {}, logReturns: () => {}, diff --git a/packages/agent/src/tools/io/fetch.ts b/packages/agent/src/tools/io/fetch.ts index b98b9dc..5982b01 100644 --- a/packages/agent/src/tools/io/fetch.ts +++ b/packages/agent/src/tools/io/fetch.ts @@ -38,8 +38,10 @@ export const fetchTool: Tool = { description: 'Executes HTTP requests using native Node.js fetch API, for using APIs, not for browsing the web.', logPrefix: '🌐', - parameters: zodToJsonSchema(parameterSchema), - returns: zodToJsonSchema(returnSchema), + parameters: parameterSchema, + returns: returnSchema, + parametersJsonSchema: zodToJsonSchema(parameterSchema), + returnsJsonSchema: zodToJsonSchema(returnSchema), execute: async ( { method, url, params, body, headers }: Parameters, { logger }, diff --git a/packages/agent/src/tools/io/readFile.ts b/packages/agent/src/tools/io/readFile.ts index 2edb166..55ee8e0 100644 --- a/packages/agent/src/tools/io/readFile.ts +++ b/packages/agent/src/tools/io/readFile.ts @@ -48,8 +48,10 @@ export const readFileTool: Tool = { name: 'readFile', description: 'Reads file content within size limits and optional range', logPrefix: '📖', - parameters: zodToJsonSchema(parameterSchema), - returns: zodToJsonSchema(returnSchema), + parameters: parameterSchema, + returns: returnSchema, + parametersJsonSchema: zodToJsonSchema(parameterSchema), + returnsJsonSchema: zodToJsonSchema(returnSchema), execute: async ( { path: filePath, range, maxSize = OUTPUT_LIMIT }, context, diff --git a/packages/agent/src/tools/io/updateFile.ts b/packages/agent/src/tools/io/updateFile.ts index 3355344..007ddf6 100644 --- a/packages/agent/src/tools/io/updateFile.ts +++ b/packages/agent/src/tools/io/updateFile.ts @@ -45,8 +45,10 @@ export const updateFileTool: Tool = { description: 'Creates a file or updates a file by rewriting, patching, or appending content', logPrefix: '📝', - parameters: zodToJsonSchema(parameterSchema), - returns: zodToJsonSchema(returnSchema), + parameters: parameterSchema, + returns: returnSchema, + parametersJsonSchema: zodToJsonSchema(parameterSchema), + returnsJsonSchema: zodToJsonSchema(returnSchema), execute: async ( { path: filePath, operation }, { logger, workingDirectory }, diff --git a/packages/agent/src/tools/system/respawn.ts b/packages/agent/src/tools/system/respawn.ts index 6b0030e..1640764 100644 --- a/packages/agent/src/tools/system/respawn.ts +++ b/packages/agent/src/tools/system/respawn.ts @@ -1,29 +1,31 @@ +import { z } from 'zod'; +import { zodToJsonSchema } from 'zod-to-json-schema'; + import { Tool, ToolContext } from '../../core/types.js'; export interface RespawnInput { respawnContext: string; } +const parameterSchema = z.object({ + respawnContext: z.string().describe('The context to keep after respawning'), +}); + +const returnSchema = z.object({ + result: z + .string() + .describe('A message indicating that the respawn has been initiated'), +}); + export const respawnTool: Tool = { name: 'respawn', description: 'Resets the agent context to just the system prompt and provided context', logPrefix: '🔄', - parameters: { - type: 'object', - properties: { - respawnContext: { - type: 'string', - description: 'The context to keep after respawning', - }, - }, - required: ['respawnContext'], - additionalProperties: false, - }, - returns: { - type: 'string', - description: 'A message indicating that the respawn has been initiated', - }, + parameters: parameterSchema, + returns: returnSchema, + parametersJsonSchema: zodToJsonSchema(parameterSchema), + returnsJsonSchema: zodToJsonSchema(returnSchema), execute: ( _params: Record, _context: ToolContext, diff --git a/packages/agent/src/tools/system/sequenceComplete.ts b/packages/agent/src/tools/system/sequenceComplete.ts index 037ef5b..cb3bf1f 100644 --- a/packages/agent/src/tools/system/sequenceComplete.ts +++ b/packages/agent/src/tools/system/sequenceComplete.ts @@ -7,9 +7,11 @@ const parameterSchema = z.object({ result: z.string().describe('The final result to return from the tool agent'), }); -const returnSchema = z - .string() - .describe('This is returned to the caller of the tool agent.'); +const returnSchema = z.object({ + result: z + .string() + .describe('This is returned to the caller of the tool agent.'), +}); type Parameters = z.infer; type ReturnType = z.infer; @@ -18,9 +20,11 @@ export const sequenceCompleteTool: Tool = { name: 'sequenceComplete', description: 'Completes the tool use sequence and returns the final result', logPrefix: '✅', - parameters: zodToJsonSchema(parameterSchema), - returns: zodToJsonSchema(returnSchema), - execute: ({ result }) => Promise.resolve(result), + parameters: parameterSchema, + parametersJsonSchema: zodToJsonSchema(parameterSchema), + returns: returnSchema, + returnsJsonSchema: zodToJsonSchema(returnSchema), + execute: ({ result }) => Promise.resolve({ result }), logParameters: () => {}, logReturns: (output, { logger }) => { logger.info(`Completed: ${output}`); diff --git a/packages/agent/src/tools/system/shellExecute.ts b/packages/agent/src/tools/system/shellExecute.ts index d042734..4fbe278 100644 --- a/packages/agent/src/tools/system/shellExecute.ts +++ b/packages/agent/src/tools/system/shellExecute.ts @@ -48,8 +48,10 @@ export const shellExecuteTool: Tool = { logPrefix: '💻', description: 'Executes a bash shell command and returns its output, can do amazing things if you are a shell scripting wizard', - parameters: zodToJsonSchema(parameterSchema), - returns: zodToJsonSchema(returnSchema), + parameters: parameterSchema, + returns: returnSchema, + parametersJsonSchema: zodToJsonSchema(parameterSchema), + returnsJsonSchema: zodToJsonSchema(returnSchema), execute: async ( { command, timeout = 30000 }, diff --git a/packages/agent/src/tools/system/shellMessage.ts b/packages/agent/src/tools/system/shellMessage.ts index c774500..d25e288 100644 --- a/packages/agent/src/tools/system/shellMessage.ts +++ b/packages/agent/src/tools/system/shellMessage.ts @@ -77,8 +77,10 @@ export const shellMessageTool: Tool = { description: 'Interacts with a running shell process, sending input and receiving output', logPrefix: '💻', - parameters: zodToJsonSchema(parameterSchema), - returns: zodToJsonSchema(returnSchema), + parameters: parameterSchema, + parametersJsonSchema: zodToJsonSchema(parameterSchema), + returns: returnSchema, + returnsJsonSchema: zodToJsonSchema(returnSchema), execute: async ( { instanceId, stdin, signal }, diff --git a/packages/agent/src/tools/system/shellStart.ts b/packages/agent/src/tools/system/shellStart.ts index 810e7f4..60508ca 100644 --- a/packages/agent/src/tools/system/shellStart.ts +++ b/packages/agent/src/tools/system/shellStart.ts @@ -72,8 +72,10 @@ export const shellStartTool: Tool = { description: 'Starts a shell command with fast sync mode (default 100ms timeout) that falls back to async mode for longer-running commands', logPrefix: '💻', - parameters: zodToJsonSchema(parameterSchema), - returns: zodToJsonSchema(returnSchema), + parameters: parameterSchema, + returns: returnSchema, + parametersJsonSchema: zodToJsonSchema(parameterSchema), + returnsJsonSchema: zodToJsonSchema(returnSchema), execute: async ( { command, timeout = DEFAULT_TIMEOUT }, diff --git a/packages/agent/src/tools/system/sleep.ts b/packages/agent/src/tools/system/sleep.ts index 5ff84f2..fc28062 100644 --- a/packages/agent/src/tools/system/sleep.ts +++ b/packages/agent/src/tools/system/sleep.ts @@ -23,8 +23,10 @@ export const sleepTool: Tool = { description: 'Pauses execution for the specified number of seconds, useful when waiting for async tools to make progress before checking on them', logPrefix: '💤', - parameters: zodToJsonSchema(parametersSchema), - returns: zodToJsonSchema(returnsSchema), + parameters: parametersSchema, + returns: returnsSchema, + parametersJsonSchema: zodToJsonSchema(parametersSchema), + returnsJsonSchema: zodToJsonSchema(returnsSchema), async execute(params) { const { seconds } = parametersSchema.parse(params); diff --git a/packages/cli/src/commands/$default.ts b/packages/cli/src/commands/$default.ts index 01959ac..8b06b2d 100644 --- a/packages/cli/src/commands/$default.ts +++ b/packages/cli/src/commands/$default.ts @@ -10,6 +10,7 @@ import { userPrompt, LogLevel, subAgentTool, + errorToString, } from 'mycoder-agent'; import { TokenTracker } from 'mycoder-agent/dist/core/tokens.js'; @@ -148,7 +149,11 @@ export const command: CommandModule = { : JSON.stringify(result.result, null, 2); logger.info('\n=== Result ===\n', output); } catch (error) { - logger.error('An error occurred:', error); + logger.error( + 'An error occurred:', + errorToString(error), + error instanceof Error ? error.stack : '', + ); // Capture the error with Sentry captureException(error); } diff --git a/packages/cli/src/commands/tools.ts b/packages/cli/src/commands/tools.ts index 7b1e580..5656a0e 100644 --- a/packages/cli/src/commands/tools.ts +++ b/packages/cli/src/commands/tools.ts @@ -43,19 +43,22 @@ export const command: CommandModule = { try { const tools = getTools(); - console.log('Available Tools:\\n'); + console.log('Available Tools:\n'); for (const tool of tools) { // Tool name and description console.log(`${tool.name}`); console.log('-'.repeat(tool.name.length)); - console.log(`Description: ${tool.description}\\n`); + console.log(`Description: ${tool.description}\n`); // Parameters section console.log('Parameters:'); + // Use parametersJsonSchema if available, otherwise convert from ZodSchema + const parametersSchema = + (tool as any).parametersJsonSchema || tool.parameters; console.log( formatSchema( - tool.parameters as { + parametersSchema as { properties?: Record; required?: string[]; }, @@ -65,9 +68,11 @@ export const command: CommandModule = { // Returns section console.log('Returns:'); if (tool.returns) { + // Use returnsJsonSchema if available, otherwise convert from ZodSchema + const returnsSchema = (tool as any).returnsJsonSchema || tool.returns; console.log( formatSchema( - tool.returns as { + returnsSchema as { properties?: Record; required?: string[]; }, @@ -75,7 +80,7 @@ export const command: CommandModule = { ); } else { console.log(' Type: any'); - console.log(' Description: Tool execution result or error\\n'); + console.log(' Description: Tool execution result or error\n'); } console.log(); // Add spacing between tools diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 338de52..187b1bf 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1,19 +1,17 @@ import { createRequire } from 'module'; -import { join } from 'path'; -import { fileURLToPath } from 'url'; import * as dotenv from 'dotenv'; import sourceMapSupport from 'source-map-support'; -import yargs from 'yargs'; +import yargs, { CommandModule } from 'yargs'; import { hideBin } from 'yargs/helpers'; -import { fileCommands } from 'yargs-file-commands'; -// Initialize Sentry as early as possible +import { command as defaultCommand } from './commands/$default.js'; +import { command as testSentryCommand } from './commands/test-sentry.js'; +import { command as toolsCommand } from './commands/tools.js'; +import { sharedOptions } from './options.js'; import { initSentry, captureException } from './sentry/index.js'; initSentry(); -import { sharedOptions } from './options.js'; - import type { PackageJson } from 'type-fest'; // Add global declaration for our patched toolAgent @@ -26,10 +24,6 @@ const main = async () => { const require = createRequire(import.meta.url); const packageInfo = require('../package.json') as PackageJson; - // Get the directory where commands are located - const __filename = fileURLToPath(import.meta.url); - const commandsDir = join(__filename, '..', 'commands'); - // Set up yargs with the new CLI interface await yargs(hideBin(process.argv)) .scriptName(packageInfo.name!) @@ -37,12 +31,11 @@ const main = async () => { .options(sharedOptions) .alias('h', 'help') .alias('V', 'version') - .command( - await fileCommands({ - commandDirs: [commandsDir], - logLevel: 'info', - }), - ) + .command([ + defaultCommand, + testSentryCommand, + toolsCommand, + ] as CommandModule[]) .strict() .showHelpOnFail(true) .help().argv; diff --git a/packages/cli/src/sentry/index.ts b/packages/cli/src/sentry/index.ts index 360344d..5f9a26a 100644 --- a/packages/cli/src/sentry/index.ts +++ b/packages/cli/src/sentry/index.ts @@ -1,6 +1,7 @@ -import * as Sentry from '@sentry/node'; import { createRequire } from 'module'; +import * as Sentry from '@sentry/node'; + /** * Initialize Sentry for error tracking * @param dsn Optional custom DSN to use instead of the default @@ -10,7 +11,8 @@ export function initSentry(dsn?: string) { let packageVersion = 'unknown'; try { const require = createRequire(import.meta.url); - packageVersion = process.env.npm_package_version || require('../../package.json').version; + packageVersion = + process.env.npm_package_version || require('../../package.json').version; } catch (error) { console.warn('Could not determine package version for Sentry:', error); } @@ -18,27 +20,26 @@ export function initSentry(dsn?: string) { // Initialize Sentry Sentry.init({ // Default DSN from Sentry.io integration instructions - dsn: dsn || 'https://2873d2518b60f645918b6a08ae5e69ae@o4508898407481344.ingest.us.sentry.io/4508898476687360', - + dsn: + dsn || + 'https://2873d2518b60f645918b6a08ae5e69ae@o4508898407481344.ingest.us.sentry.io/4508898476687360', + // No profiling integration as requested - + // Capture 100% of the transactions tracesSampleRate: 1.0, - + // Set environment based on NODE_ENV environment: process.env.NODE_ENV || 'development', - + // Add release version from package.json release: `mycoder@${packageVersion}`, - + // Don't capture errors in development mode unless explicitly enabled - enabled: process.env.NODE_ENV !== 'development' || process.env.ENABLE_SENTRY === 'true', + enabled: + process.env.NODE_ENV !== 'development' || + process.env.ENABLE_SENTRY === 'true', }); - - // Log confirmation that Sentry is initialized with version info - if (process.env.NODE_ENV !== 'test') { - console.log(`Sentry initialized for mycoder@${packageVersion}`); - } } /** @@ -67,20 +68,27 @@ export function testSentryErrorReporting() { let packageVersion = 'unknown'; try { const require = createRequire(import.meta.url); - packageVersion = process.env.npm_package_version || require('../../package.json').version; + packageVersion = + process.env.npm_package_version || + require('../../package.json').version; } catch (error) { - console.warn('Could not determine package version for test error:', error); + console.warn( + 'Could not determine package version for test error:', + error, + ); } - + // Throw a test error with version information - throw new Error(`Test error for Sentry.io integration from mycoder@${packageVersion}`); + throw new Error( + `Test error for Sentry.io integration from mycoder@${packageVersion}`, + ); } catch (error) { // Capture the error with Sentry Sentry.captureException(error); - + // Log a message about the test console.log('Test error sent to Sentry.io'); - + // Return the error for inspection return error; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c2a1fd5..94c11c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,9 +54,12 @@ importers: packages/agent: dependencies: - '@anthropic-ai/sdk': - specifier: ^0.37 - version: 0.37.0 + '@ai-sdk/anthropic': + specifier: ^1.1.13 + version: 1.1.13(zod@3.24.2) + '@ai-sdk/openai': + specifier: ^1.2.0 + version: 1.2.0(zod@3.24.2) '@mozilla/readability': specifier: ^0.5.0 version: 0.5.0 @@ -66,6 +69,9 @@ importers: '@vitest/browser': specifier: ^3.0.5 version: 3.0.6(@types/node@18.19.76)(playwright@1.50.1)(typescript@5.7.3)(vite@6.1.1(@types/node@18.19.76)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(vitest@3.0.6) + ai: + specifier: ^4.1.50 + version: 4.1.50(react@19.0.0)(zod@3.24.2) chalk: specifier: ^5 version: 5.4.1 @@ -75,6 +81,9 @@ importers: jsdom: specifier: ^26.0.0 version: 26.0.0 + ollama-ai-provider: + specifier: ^1.2.0 + version: 1.2.0(zod@3.24.2) playwright: specifier: ^1.50.1 version: 1.50.1 @@ -167,8 +176,51 @@ importers: packages: - '@anthropic-ai/sdk@0.37.0': - resolution: {integrity: sha512-tHjX2YbkUBwEgg0JZU3EFSSAQPoK4qQR/NFYa8Vtzd5UAyXzZksCw2In69Rml4R/TyHPBfRYaLK35XiOe33pjw==} + '@ai-sdk/anthropic@1.1.13': + resolution: {integrity: sha512-dBivw7ggokys0c9UmbhxHW36S+EHMQEHk/hVcakGO3sMEe6Vi0dR575xDjXJqs8uZPAmbcZjNb1s89U8cA0Y+Q==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/openai@1.2.0': + resolution: {integrity: sha512-tzxH6OxKL5ffts4zJPdziQSJGGpSrQcJmuSrE92jCt7pJ4PAU5Dx4tjNNFIU8lSfwarLnywejZEt3Fz0uQZZOQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/provider-utils@2.1.10': + resolution: {integrity: sha512-4GZ8GHjOFxePFzkl3q42AU0DQOtTQ5w09vmaWUf/pKFXJPizlnzKSUkF0f+VkapIUfDugyMqPMT1ge8XQzVI7Q==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + peerDependenciesMeta: + zod: + optional: true + + '@ai-sdk/provider@1.0.9': + resolution: {integrity: sha512-jie6ZJT2ZR0uVOVCDc9R2xCX5I/Dum/wEK28lx21PJx6ZnFAN9EzD2WsPhcDWfCgGx3OAZZ0GyM3CEobXpa9LA==} + engines: {node: '>=18'} + + '@ai-sdk/react@1.1.20': + resolution: {integrity: sha512-4QOM9fR9SryaRraybckDjrhl1O6XejqELdKmrM5g9y9eLnWAfjwF+W1aN0knkSHzbbjMqN77sy9B9yL8EuJbDw==} + engines: {node: '>=18'} + peerDependencies: + react: ^18 || ^19 || ^19.0.0-rc + zod: ^3.0.0 + peerDependenciesMeta: + react: + optional: true + zod: + optional: true + + '@ai-sdk/ui-utils@1.1.16': + resolution: {integrity: sha512-jfblR2yZVISmNK2zyNzJZFtkgX57WDAUQXcmn3XUBJyo8LFsADu+/vYMn5AOyBi9qJT0RBk11PEtIxIqvByw3Q==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + peerDependenciesMeta: + zod: + optional: true '@asamuzakjp/css-color@2.8.3': resolution: {integrity: sha512-GIc76d9UI1hCvOATjZPyHFmE5qhRccp3/zGfMPapK3jBi+yocEzp6BBB0UnfRYP9NP4FANqUZYb0hnfs3TM3hw==} @@ -1080,6 +1132,9 @@ packages: '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@types/diff-match-patch@1.0.36': + resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==} + '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -1095,18 +1150,12 @@ packages: '@types/mysql@2.15.26': resolution: {integrity: sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==} - '@types/node-fetch@2.6.12': - resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==} - '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} '@types/node@18.19.76': resolution: {integrity: sha512-yvR7Q9LdPz2vGpmpJX5LolrgRdWvB67MJKDPSgIIzpFbaf9a1j/f5DnLp5VDyHGMR0QZHlTr1afsD87QCXFHKw==} - '@types/node@20.17.19': - resolution: {integrity: sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==} - '@types/pg-pool@2.0.6': resolution: {integrity: sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==} @@ -1225,10 +1274,6 @@ packages: '@vitest/utils@3.0.6': resolution: {integrity: sha512-18ktZpf4GQFTbf9jK543uspU03Q2qya7ZGya5yiZ0Gx0nnnalBvd5ZBislbl2EhLjM8A8rt4OilqKG7QwcGkvQ==} - abort-controller@3.0.0: - resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} - engines: {node: '>=6.5'} - acorn-import-attributes@1.9.5: resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} peerDependencies: @@ -1248,9 +1293,17 @@ packages: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} - agentkeepalive@4.6.0: - resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} - engines: {node: '>= 8.0.0'} + ai@4.1.50: + resolution: {integrity: sha512-YBNeemrJKDrxoBQd3V9aaxhKm5q5YyRcF7PZE7W0NmLuvsdva/1aQNYTAsxs47gQFdvqfYmlFy4B0E+356OlPA==} + engines: {node: '>=18'} + peerDependencies: + react: ^18 || ^19 || ^19.0.0-rc + zod: ^3.0.0 + peerDependenciesMeta: + react: + optional: true + zod: + optional: true ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -1501,6 +1554,9 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} + diff-match-patch@1.0.5: + resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -1722,9 +1778,9 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - event-target-shim@5.0.1: - resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} - engines: {node: '>=6'} + eventsource-parser@3.0.0: + resolution: {integrity: sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA==} + engines: {node: '>=18.0.0'} expect-type@1.1.0: resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==} @@ -1795,17 +1851,10 @@ packages: resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} engines: {node: '>=14'} - form-data-encoder@1.7.2: - resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} - form-data@4.0.2: resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} engines: {node: '>= 6'} - formdata-node@4.4.1: - resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} - engines: {node: '>= 12.20'} - forwarded-parse@2.1.2: resolution: {integrity: sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==} @@ -1945,9 +1994,6 @@ packages: resolution: {integrity: sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg==} hasBin: true - humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -2135,6 +2181,9 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -2142,6 +2191,11 @@ packages: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true + jsondiffpatch@0.6.0: + resolution: {integrity: sha512-3QItJOXp2AP1uv7waBkao5nCvhEv+QmJAd38Ybq7wNI74Q+BBmnLn4EDKz6yI9xGAIQoUF87qHt+kc1IVxB4zQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} @@ -2257,19 +2311,6 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - node-domexception@1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} - - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - nwsapi@2.2.16: resolution: {integrity: sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==} @@ -2297,6 +2338,15 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} + ollama-ai-provider@1.2.0: + resolution: {integrity: sha512-jTNFruwe3O/ruJeppI/quoOUxG7NA6blG3ZyQj3lei4+NnJo7bi3eIRWqlVpRlu/mbzbFXeJSBuYQWF6pzGKww==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + peerDependenciesMeta: + zod: + optional: true + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -2356,6 +2406,9 @@ packages: parse5@7.2.1: resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} + partial-json@0.1.7: + resolution: {integrity: sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -2487,6 +2540,10 @@ packages: react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react@19.0.0: + resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} + engines: {node: '>=0.10.0'} + read-yaml-file@1.1.0: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} @@ -2572,6 +2629,9 @@ packages: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -2712,6 +2772,11 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + swr@2.3.2: + resolution: {integrity: sha512-RosxFpiabojs75IwQ316DGoDRmOqtiAj0tg8wCcbEu4CiLZBs/a9QNtHV7TUfDXmmlgqij/NqzKq/eLelyv9xA==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} @@ -2732,6 +2797,10 @@ packages: engines: {node: '>=10'} hasBin: true + throttleit@2.1.0: + resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} + engines: {node: '>=18'} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -2781,9 +2850,6 @@ packages: resolution: {integrity: sha512-Ek7HndSVkp10hmHP9V4qZO1u+pn1RU5sI0Fw+jCU3lyvuMZcgqsNgc6CmJJZyByK4Vm/qotGRJlfgAX8q+4JiA==} engines: {node: '>=16'} - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tr46@5.0.0: resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==} engines: {node: '>=18'} @@ -2852,9 +2918,6 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -2869,6 +2932,11 @@ packages: url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + use-sync-external-store@1.4.0: + resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + uuid@11.1.0: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true @@ -2950,13 +3018,6 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} - web-streams-polyfill@4.0.0-beta.3: - resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} - engines: {node: '>= 14'} - - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} @@ -2973,9 +3034,6 @@ packages: resolution: {integrity: sha512-mDGf9diDad/giZ/Sm9Xi2YcyzaFpbdLpJPr+E9fSkyQ7KpQD4SdFcugkRQYzhmfI4KeV4Qpnn2sKPdo+kmsgRQ==} engines: {node: '>=18'} - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -3082,17 +3140,48 @@ packages: snapshots: - '@anthropic-ai/sdk@0.37.0': + '@ai-sdk/anthropic@1.1.13(zod@3.24.2)': dependencies: - '@types/node': 18.19.76 - '@types/node-fetch': 2.6.12 - abort-controller: 3.0.0 - agentkeepalive: 4.6.0 - form-data-encoder: 1.7.2 - formdata-node: 4.4.1 - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding + '@ai-sdk/provider': 1.0.9 + '@ai-sdk/provider-utils': 2.1.10(zod@3.24.2) + zod: 3.24.2 + + '@ai-sdk/openai@1.2.0(zod@3.24.2)': + dependencies: + '@ai-sdk/provider': 1.0.9 + '@ai-sdk/provider-utils': 2.1.10(zod@3.24.2) + zod: 3.24.2 + + '@ai-sdk/provider-utils@2.1.10(zod@3.24.2)': + dependencies: + '@ai-sdk/provider': 1.0.9 + eventsource-parser: 3.0.0 + nanoid: 3.3.8 + secure-json-parse: 2.7.0 + optionalDependencies: + zod: 3.24.2 + + '@ai-sdk/provider@1.0.9': + dependencies: + json-schema: 0.4.0 + + '@ai-sdk/react@1.1.20(react@19.0.0)(zod@3.24.2)': + dependencies: + '@ai-sdk/provider-utils': 2.1.10(zod@3.24.2) + '@ai-sdk/ui-utils': 1.1.16(zod@3.24.2) + swr: 2.3.2(react@19.0.0) + throttleit: 2.1.0 + optionalDependencies: + react: 19.0.0 + zod: 3.24.2 + + '@ai-sdk/ui-utils@1.1.16(zod@3.24.2)': + dependencies: + '@ai-sdk/provider': 1.0.9 + '@ai-sdk/provider-utils': 2.1.10(zod@3.24.2) + zod-to-json-schema: 3.24.3(zod@3.24.2) + optionalDependencies: + zod: 3.24.2 '@asamuzakjp/css-color@2.8.3': dependencies: @@ -4013,6 +4102,8 @@ snapshots: '@types/ms': 2.1.0 optional: true + '@types/diff-match-patch@1.0.36': {} + '@types/estree@1.0.6': {} '@types/json-schema@7.0.15': {} @@ -4026,21 +4117,12 @@ snapshots: dependencies: '@types/node': 18.19.76 - '@types/node-fetch@2.6.12': - dependencies: - '@types/node': 20.17.19 - form-data: 4.0.2 - '@types/node@12.20.55': {} '@types/node@18.19.76': dependencies: undici-types: 5.26.5 - '@types/node@20.17.19': - dependencies: - undici-types: 6.19.8 - '@types/pg-pool@2.0.6': dependencies: '@types/pg': 8.6.1 @@ -4208,10 +4290,6 @@ snapshots: loupe: 3.1.3 tinyrainbow: 2.0.0 - abort-controller@3.0.0: - dependencies: - event-target-shim: 5.0.1 - acorn-import-attributes@1.9.5(acorn@8.14.0): dependencies: acorn: 8.14.0 @@ -4224,9 +4302,17 @@ snapshots: agent-base@7.1.3: {} - agentkeepalive@4.6.0: + ai@4.1.50(react@19.0.0)(zod@3.24.2): dependencies: - humanize-ms: 1.2.1 + '@ai-sdk/provider': 1.0.9 + '@ai-sdk/provider-utils': 2.1.10(zod@3.24.2) + '@ai-sdk/react': 1.1.20(react@19.0.0)(zod@3.24.2) + '@ai-sdk/ui-utils': 1.1.16(zod@3.24.2) + '@opentelemetry/api': 1.9.0 + jsondiffpatch: 0.6.0 + optionalDependencies: + react: 19.0.0 + zod: 3.24.2 ajv@6.12.6: dependencies: @@ -4478,6 +4564,8 @@ snapshots: detect-indent@6.1.0: {} + diff-match-patch@1.0.5: {} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 @@ -4817,7 +4905,7 @@ snapshots: esutils@2.0.3: {} - event-target-shim@5.0.1: {} + eventsource-parser@3.0.0: {} expect-type@1.1.0: {} @@ -4887,8 +4975,6 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - form-data-encoder@1.7.2: {} - form-data@4.0.2: dependencies: asynckit: 0.4.0 @@ -4896,11 +4982,6 @@ snapshots: es-set-tostringtag: 2.1.0 mime-types: 2.1.35 - formdata-node@4.4.1: - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 4.0.0-beta.3 - forwarded-parse@2.1.2: {} fs-extra@7.0.1: @@ -5058,10 +5139,6 @@ snapshots: human-id@4.1.1: {} - humanize-ms@1.2.1: - dependencies: - ms: 2.1.3 - iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -5273,12 +5350,20 @@ snapshots: json-schema-traverse@0.4.1: {} + json-schema@0.4.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json5@1.0.2: dependencies: minimist: 1.2.8 + jsondiffpatch@0.6.0: + dependencies: + '@types/diff-match-patch': 1.0.36 + chalk: 5.4.1 + diff-match-patch: 1.0.5 + jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.11 @@ -5386,12 +5471,6 @@ snapshots: natural-compare@1.4.0: {} - node-domexception@1.0.0: {} - - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - nwsapi@2.2.16: {} object-inspect@1.13.4: {} @@ -5427,6 +5506,14 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + ollama-ai-provider@1.2.0(zod@3.24.2): + dependencies: + '@ai-sdk/provider': 1.0.9 + '@ai-sdk/provider-utils': 2.1.10(zod@3.24.2) + partial-json: 0.1.7 + optionalDependencies: + zod: 3.24.2 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -5484,6 +5571,8 @@ snapshots: dependencies: entities: 4.5.0 + partial-json@0.1.7: {} + path-exists@4.0.0: {} path-key@3.1.1: {} @@ -5582,6 +5671,8 @@ snapshots: react-is@17.0.2: {} + react@19.0.0: {} + read-yaml-file@1.1.0: dependencies: graceful-fs: 4.2.11 @@ -5702,6 +5793,8 @@ snapshots: dependencies: xmlchars: 2.2.0 + secure-json-parse@2.7.0: {} + semver@6.3.1: {} semver@7.7.1: {} @@ -5855,6 +5948,12 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + swr@2.3.2(react@19.0.0): + dependencies: + dequal: 2.0.3 + react: 19.0.0 + use-sync-external-store: 1.4.0(react@19.0.0) + symbol-tree@3.2.4: {} synckit@0.9.2: @@ -5874,6 +5973,8 @@ snapshots: source-map-support: 0.5.21 optional: true + throttleit@2.1.0: {} + tinybench@2.9.0: {} tinyexec@0.3.2: {} @@ -5916,8 +6017,6 @@ snapshots: dependencies: tldts: 6.1.79 - tr46@0.0.3: {} - tr46@5.0.0: dependencies: punycode: 2.3.1 @@ -6005,8 +6104,6 @@ snapshots: undici-types@5.26.5: {} - undici-types@6.19.8: {} - universalify@0.1.2: {} universalify@0.2.0: {} @@ -6020,6 +6117,10 @@ snapshots: querystringify: 2.2.0 requires-port: 1.0.0 + use-sync-external-store@1.4.0(react@19.0.0): + dependencies: + react: 19.0.0 + uuid@11.1.0: {} vite-node@3.0.6(@types/node@18.19.76)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0): @@ -6101,10 +6202,6 @@ snapshots: dependencies: xml-name-validator: 5.0.0 - web-streams-polyfill@4.0.0-beta.3: {} - - webidl-conversions@3.0.1: {} - webidl-conversions@7.0.0: {} whatwg-encoding@3.1.1: @@ -6118,11 +6215,6 @@ snapshots: tr46: 5.0.0 webidl-conversions: 7.0.0 - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0