diff --git a/packages/agent/CHANGELOG.md b/packages/agent/CHANGELOG.md index 5dd4618..6606f57 100644 --- a/packages/agent/CHANGELOG.md +++ b/packages/agent/CHANGELOG.md @@ -1,3 +1,25 @@ +# [mycoder-agent-v1.1.0](https://github.com/drivecore/mycoder/compare/mycoder-agent-v1.0.0...mycoder-agent-v1.1.0) (2025-03-12) + +### Bug Fixes + +- convert absolute paths to relative paths in textEditor log output ([a5ea845](https://github.com/drivecore/mycoder/commit/a5ea845c32bc569cda4330f59f1bf1553a236aea)) +- implement resource cleanup to prevent CLI hanging issue ([d33e729](https://github.com/drivecore/mycoder/commit/d33e7298686a30661ee8b36f2fdffb16f5f3da71)), closes [#141](https://github.com/drivecore/mycoder/issues/141) +- llm choice working well for openai, anthropic and ollama ([68d34ab](https://github.com/drivecore/mycoder/commit/68d34abf8a73ed533a072359ce334a9364753425)) +- **openai:** add OpenAI dependency to agent package and enable provider in config ([30b0807](https://github.com/drivecore/mycoder/commit/30b0807d4f3ecdd24f53b7ee4160645a4ed10444)) +- replace @semantic-release/npm with @anolilab/semantic-release-pnpm to properly resolve workspace references ([bacb51f](https://github.com/drivecore/mycoder/commit/bacb51f637f2b2d3b1039bdfdbd33e3d704b6cde)) +- up subagent iterations to 200 from 50 ([b405f1e](https://github.com/drivecore/mycoder/commit/b405f1e6d62eb5304dc1aa6c0ff28dc49dc67dce)) + +### Features + +- add agent tracking to background tools ([4a3bcc7](https://github.com/drivecore/mycoder/commit/4a3bcc72f27af5fdbeeb407a748d5ecf3b7faed5)) +- add Ollama configuration options ([d5c3a96](https://github.com/drivecore/mycoder/commit/d5c3a96ce9463c98504c2a346796400df36bf3b0)) +- **agent:** implement agentStart and agentMessage tools ([62f8df3](https://github.com/drivecore/mycoder/commit/62f8df3dd083e2838c97ce89112f390461550ee6)), closes [#111](https://github.com/drivecore/mycoder/issues/111) [#111](https://github.com/drivecore/mycoder/issues/111) +- allow textEditor to overwrite existing files with create command ([d1cde65](https://github.com/drivecore/mycoder/commit/d1cde65df65bfcca288a47f14eedf5ad5939ed37)), closes [#192](https://github.com/drivecore/mycoder/issues/192) +- implement background tool tracking (issue [#112](https://github.com/drivecore/mycoder/issues/112)) ([b5bb489](https://github.com/drivecore/mycoder/commit/b5bb48981791acda74ee46b93d2d85e27e93a538)) +- implement Ollama provider for LLM abstraction ([597211b](https://github.com/drivecore/mycoder/commit/597211b90e43c4d52969eb5994d393c15d85ec97)) +- **llm:** add OpenAI support to LLM abstraction ([7bda811](https://github.com/drivecore/mycoder/commit/7bda811658e15b8dd41135cd9b2b90e9ea925e15)) +- **refactor:** agent ([a2f59c2](https://github.com/drivecore/mycoder/commit/a2f59c2f51643a44d6e1ff0c16b319deb1adc3f2)) + # mycoder-agent-v1.0.0 (2025-03-11) ### Bug Fixes diff --git a/packages/agent/package.json b/packages/agent/package.json index 6511def..24baa66 100644 --- a/packages/agent/package.json +++ b/packages/agent/package.json @@ -1,6 +1,6 @@ { "name": "mycoder-agent", - "version": "1.0.1", + "version": "1.1.0", "description": "Agent module for mycoder - an AI-powered software development assistant", "type": "module", "main": "dist/index.js", diff --git a/packages/agent/src/core/backgroundTools.test.ts b/packages/agent/src/core/backgroundTools.test.ts index ec75544..4b0e5c3 100644 --- a/packages/agent/src/core/backgroundTools.test.ts +++ b/packages/agent/src/core/backgroundTools.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it, vi, beforeEach } from 'vitest'; import { - backgroundToolRegistry, + BackgroundTools, BackgroundToolStatus, BackgroundToolType, } from './backgroundTools.js'; @@ -12,23 +12,23 @@ vi.mock('uuid', () => ({ })); describe('BackgroundToolRegistry', () => { + let backgroundTools: BackgroundTools; beforeEach(() => { // Clear all registered tools before each test - const registry = backgroundToolRegistry as any; - registry.tools = new Map(); + backgroundTools = new BackgroundTools('test'); + backgroundTools.tools = new Map(); }); it('should register a shell process', () => { - const id = backgroundToolRegistry.registerShell('agent-1', 'ls -la'); + const id = backgroundTools.registerShell('ls -la'); expect(id).toBe('test-id-1'); - const tool = backgroundToolRegistry.getToolById(id); + const tool = backgroundTools.getToolById(id); expect(tool).toBeDefined(); if (tool) { expect(tool.type).toBe(BackgroundToolType.SHELL); expect(tool.status).toBe(BackgroundToolStatus.RUNNING); - expect(tool.agentId).toBe('agent-1'); if (tool.type === BackgroundToolType.SHELL) { expect(tool.metadata.command).toBe('ls -la'); } @@ -36,19 +36,15 @@ describe('BackgroundToolRegistry', () => { }); it('should register a browser process', () => { - const id = backgroundToolRegistry.registerBrowser( - 'agent-1', - 'https://example.com', - ); + const id = backgroundTools.registerBrowser('https://example.com'); expect(id).toBe('test-id-1'); - const tool = backgroundToolRegistry.getToolById(id); + const tool = backgroundTools.getToolById(id); expect(tool).toBeDefined(); if (tool) { expect(tool.type).toBe(BackgroundToolType.BROWSER); expect(tool.status).toBe(BackgroundToolStatus.RUNNING); - expect(tool.agentId).toBe('agent-1'); if (tool.type === BackgroundToolType.BROWSER) { expect(tool.metadata.url).toBe('https://example.com'); } @@ -56,9 +52,9 @@ describe('BackgroundToolRegistry', () => { }); it('should update tool status', () => { - const id = backgroundToolRegistry.registerShell('agent-1', 'sleep 10'); + const id = backgroundTools.registerShell('sleep 10'); - const updated = backgroundToolRegistry.updateToolStatus( + const updated = backgroundTools.updateToolStatus( id, BackgroundToolStatus.COMPLETED, { @@ -68,7 +64,7 @@ describe('BackgroundToolRegistry', () => { expect(updated).toBe(true); - const tool = backgroundToolRegistry.getToolById(id); + const tool = backgroundTools.getToolById(id); expect(tool).toBeDefined(); if (tool) { expect(tool.status).toBe(BackgroundToolStatus.COMPLETED); @@ -80,7 +76,7 @@ describe('BackgroundToolRegistry', () => { }); it('should return false when updating non-existent tool', () => { - const updated = backgroundToolRegistry.updateToolStatus( + const updated = backgroundTools.updateToolStatus( 'non-existent-id', BackgroundToolStatus.COMPLETED, ); @@ -88,49 +84,9 @@ describe('BackgroundToolRegistry', () => { expect(updated).toBe(false); }); - it('should get tools by agent ID', () => { - // For this test, we'll directly manipulate the tools map - const registry = backgroundToolRegistry as any; - registry.tools = new Map(); - - // Add tools directly to the map with different agent IDs - registry.tools.set('id1', { - id: 'id1', - type: BackgroundToolType.SHELL, - status: BackgroundToolStatus.RUNNING, - startTime: new Date(), - agentId: 'agent-1', - metadata: { command: 'ls -la' }, - }); - - registry.tools.set('id2', { - id: 'id2', - type: BackgroundToolType.BROWSER, - status: BackgroundToolStatus.RUNNING, - startTime: new Date(), - agentId: 'agent-1', - metadata: { url: 'https://example.com' }, - }); - - registry.tools.set('id3', { - id: 'id3', - type: BackgroundToolType.SHELL, - status: BackgroundToolStatus.RUNNING, - startTime: new Date(), - agentId: 'agent-2', - metadata: { command: 'echo hello' }, - }); - - const agent1Tools = backgroundToolRegistry.getToolsByAgent('agent-1'); - const agent2Tools = backgroundToolRegistry.getToolsByAgent('agent-2'); - - expect(agent1Tools.length).toBe(2); - expect(agent2Tools.length).toBe(1); - }); - it('should clean up old completed tools', () => { // Create tools with specific dates - const registry = backgroundToolRegistry as any; + const registry = backgroundTools as any; // Add a completed tool from 25 hours ago const oldTool = { @@ -167,19 +123,5 @@ describe('BackgroundToolRegistry', () => { registry.tools.set('old-tool', oldTool); registry.tools.set('recent-tool', recentTool); registry.tools.set('old-running-tool', oldRunningTool); - - // Clean up tools older than 24 hours - backgroundToolRegistry.cleanupOldTools(24); - - // Old completed tool should be removed - expect(backgroundToolRegistry.getToolById('old-tool')).toBeUndefined(); - - // Recent completed tool should remain - expect(backgroundToolRegistry.getToolById('recent-tool')).toBeDefined(); - - // Old running tool should remain (not completed) - expect( - backgroundToolRegistry.getToolById('old-running-tool'), - ).toBeDefined(); }); }); diff --git a/packages/agent/src/core/backgroundTools.ts b/packages/agent/src/core/backgroundTools.ts index ebe850b..8e034c3 100644 --- a/packages/agent/src/core/backgroundTools.ts +++ b/packages/agent/src/core/backgroundTools.ts @@ -22,7 +22,6 @@ export interface BackgroundTool { status: BackgroundToolStatus; startTime: Date; endTime?: Date; - agentId: string; // To track which agent created this process metadata: Record; // Additional tool-specific information } @@ -61,30 +60,20 @@ export type AnyBackgroundTool = /** * Registry to keep track of all background processes */ -export class BackgroundToolRegistry { - private static instance: BackgroundToolRegistry; - private tools: Map = new Map(); +export class BackgroundTools { + tools: Map = new Map(); // Private constructor for singleton pattern - private constructor() {} - - // Get the singleton instance - public static getInstance(): BackgroundToolRegistry { - if (!BackgroundToolRegistry.instance) { - BackgroundToolRegistry.instance = new BackgroundToolRegistry(); - } - return BackgroundToolRegistry.instance; - } + constructor(readonly ownerName: string) {} // Register a new shell process - public registerShell(agentId: string, command: string): string { + public registerShell(command: string): string { const id = uuidv4(); const tool: ShellBackgroundTool = { id, type: BackgroundToolType.SHELL, status: BackgroundToolStatus.RUNNING, startTime: new Date(), - agentId, metadata: { command, }, @@ -94,14 +83,13 @@ export class BackgroundToolRegistry { } // Register a new browser process - public registerBrowser(agentId: string, url?: string): string { + public registerBrowser(url?: string): string { const id = uuidv4(); const tool: BrowserBackgroundTool = { id, type: BackgroundToolType.BROWSER, status: BackgroundToolStatus.RUNNING, startTime: new Date(), - agentId, metadata: { url, }, @@ -111,14 +99,13 @@ export class BackgroundToolRegistry { } // Register a new agent process (for future use) - public registerAgent(agentId: string, goal?: string): string { + public registerAgent(goal?: string): string { const id = uuidv4(); const tool: AgentBackgroundTool = { id, type: BackgroundToolType.AGENT, status: BackgroundToolStatus.RUNNING, startTime: new Date(), - agentId, metadata: { goal, }, @@ -155,13 +142,10 @@ export class BackgroundToolRegistry { return true; } - // Get all processes for a specific agent - public getToolsByAgent(agentId: string): AnyBackgroundTool[] { + public getTools(): AnyBackgroundTool[] { const result: AnyBackgroundTool[] = []; for (const tool of this.tools.values()) { - if (tool.agentId === agentId) { - result.push(tool); - } + result.push(tool); } return result; } @@ -170,25 +154,4 @@ export class BackgroundToolRegistry { public getToolById(id: string): AnyBackgroundTool | undefined { return this.tools.get(id); } - - // Clean up completed processes (optional, for maintenance) - public cleanupOldTools(olderThanHours: number = 24): void { - const cutoffTime = new Date(Date.now() - olderThanHours * 60 * 60 * 1000); - - for (const [id, tool] of this.tools.entries()) { - // Remove if it's completed/error/terminated AND older than cutoff - if ( - tool.endTime && - tool.endTime < cutoffTime && - (tool.status === BackgroundToolStatus.COMPLETED || - tool.status === BackgroundToolStatus.ERROR || - tool.status === BackgroundToolStatus.TERMINATED) - ) { - this.tools.delete(id); - } - } - } } - -// Export singleton instance -export const backgroundToolRegistry = BackgroundToolRegistry.getInstance(); diff --git a/packages/agent/src/core/toolAgent/toolAgentCore.ts b/packages/agent/src/core/toolAgent/toolAgentCore.ts index da00326..057bb5a 100644 --- a/packages/agent/src/core/toolAgent/toolAgentCore.ts +++ b/packages/agent/src/core/toolAgent/toolAgentCore.ts @@ -39,11 +39,15 @@ export const toolAgent = async ( logger.debug('User message:', initialPrompt); + const localContext = { + ...context, + }; + // Get the system prompt once at the start - const systemPrompt = config.getSystemPrompt(context); + const systemPrompt = config.getSystemPrompt(localContext); // Create the LLM provider - const provider = createProvider(context.provider, context.model); + const provider = createProvider(localContext.provider, localContext.model); for (let i = 0; i < config.maxIterations; i++) { logger.verbose( @@ -74,8 +78,8 @@ export const toolAgent = async ( const generateOptions = { messages: messagesWithSystem, functions: functionDefinitions, - temperature: context.temperature, - maxTokens: context.maxTokens, + temperature: localContext.temperature, + maxTokens: localContext.maxTokens, }; const { text, toolCalls, tokenUsage } = await generateText( @@ -123,7 +127,7 @@ export const toolAgent = async ( // Execute the tools and get results const { sequenceCompleted, completionResult, respawn } = - await executeTools(toolCalls, tools, messages, context); + await executeTools(toolCalls, tools, messages, localContext); if (respawn) { logger.info('Respawning agent with new context'); diff --git a/packages/agent/src/core/types.ts b/packages/agent/src/core/types.ts index 59c70d0..a1871f0 100644 --- a/packages/agent/src/core/types.ts +++ b/packages/agent/src/core/types.ts @@ -3,6 +3,7 @@ import { JsonSchema7Type } from 'zod-to-json-schema'; import { Logger } from '../utils/logger.js'; +import { BackgroundTools } from './backgroundTools.js'; import { TokenTracker } from './tokens.js'; import { ModelProvider } from './toolAgent/config.js'; @@ -26,6 +27,7 @@ export type ToolContext = { model: string; maxTokens: number; temperature: number; + backgroundTools: BackgroundTools; }; export type Tool, TReturn = any> = { diff --git a/packages/agent/src/tools/browser/browseMessage.ts b/packages/agent/src/tools/browser/browseMessage.ts index abe07c3..a6b35d5 100644 --- a/packages/agent/src/tools/browser/browseMessage.ts +++ b/packages/agent/src/tools/browser/browseMessage.ts @@ -1,10 +1,7 @@ import { z } from 'zod'; import { zodToJsonSchema } from 'zod-to-json-schema'; -import { - backgroundToolRegistry, - BackgroundToolStatus, -} from '../../core/backgroundTools.js'; +import { BackgroundToolStatus } from '../../core/backgroundTools.js'; import { Tool } from '../../core/types.js'; import { errorToString } from '../../utils/errorToString.js'; import { sleep } from '../../utils/sleep.js'; @@ -75,7 +72,7 @@ export const browseMessageTool: Tool = { execute: async ( { instanceId, actionType, url, selector, selectorType, text }, - { logger, pageFilter }, + { logger, pageFilter, backgroundTools }, ): Promise => { // Validate action format @@ -190,7 +187,7 @@ export const browseMessageTool: Tool = { browserSessions.delete(instanceId); // Update background tool registry when browser is explicitly closed - backgroundToolRegistry.updateToolStatus( + backgroundTools.updateToolStatus( instanceId, BackgroundToolStatus.COMPLETED, { @@ -210,14 +207,10 @@ export const browseMessageTool: Tool = { logger.error('Browser action failed:', { error }); // Update background tool registry with error status if action fails - backgroundToolRegistry.updateToolStatus( - instanceId, - BackgroundToolStatus.ERROR, - { - error: errorToString(error), - actionType, - }, - ); + backgroundTools.updateToolStatus(instanceId, BackgroundToolStatus.ERROR, { + error: errorToString(error), + actionType, + }); return { status: 'error', diff --git a/packages/agent/src/tools/browser/browseStart.ts b/packages/agent/src/tools/browser/browseStart.ts index 8d95000..ad41298 100644 --- a/packages/agent/src/tools/browser/browseStart.ts +++ b/packages/agent/src/tools/browser/browseStart.ts @@ -3,10 +3,7 @@ import { v4 as uuidv4 } from 'uuid'; import { z } from 'zod'; import { zodToJsonSchema } from 'zod-to-json-schema'; -import { - backgroundToolRegistry, - BackgroundToolStatus, -} from '../../core/backgroundTools.js'; +import { BackgroundToolStatus } from '../../core/backgroundTools.js'; import { Tool } from '../../core/types.js'; import { errorToString } from '../../utils/errorToString.js'; import { sleep } from '../../utils/sleep.js'; @@ -46,7 +43,7 @@ export const browseStartTool: Tool = { execute: async ( { url, timeout = 30000 }, - { logger, headless, userSession, pageFilter, agentId }, + { logger, headless, userSession, pageFilter, backgroundTools }, ): Promise => { logger.verbose(`Starting browser session${url ? ` at ${url}` : ''}`); logger.verbose( @@ -58,7 +55,7 @@ export const browseStartTool: Tool = { const instanceId = uuidv4(); // Register this browser session with the background tool registry - backgroundToolRegistry.registerBrowser(agentId || 'unknown', url); + backgroundTools.registerBrowser(url); // Launch browser const launchOptions = { @@ -99,7 +96,7 @@ export const browseStartTool: Tool = { browser.on('disconnected', () => { browserSessions.delete(instanceId); // Update background tool registry when browser disconnects - backgroundToolRegistry.updateToolStatus( + backgroundTools.updateToolStatus( instanceId, BackgroundToolStatus.TERMINATED, ); @@ -146,7 +143,7 @@ export const browseStartTool: Tool = { logger.verbose(`Content length: ${content.length} characters`); // Update background tool registry with running status - backgroundToolRegistry.updateToolStatus( + backgroundTools.updateToolStatus( instanceId, BackgroundToolStatus.RUNNING, { diff --git a/packages/agent/src/tools/getTools.test.ts b/packages/agent/src/tools/getTools.test.ts index 45965fe..211e116 100644 --- a/packages/agent/src/tools/getTools.test.ts +++ b/packages/agent/src/tools/getTools.test.ts @@ -1,5 +1,6 @@ import { describe, it, expect } from 'vitest'; +import { BackgroundTools } from '../core/backgroundTools.js'; import { TokenTracker } from '../core/tokens.js'; import { ToolContext } from '../core/types.js'; import { MockLogger } from '../utils/mockLogger.js'; @@ -19,6 +20,7 @@ export const getMockToolContext = (): ToolContext => ({ model: 'claude-3-7-sonnet-20250219', maxTokens: 4096, temperature: 0.7, + backgroundTools: new BackgroundTools('test'), }); describe('getTools', () => { diff --git a/packages/agent/src/tools/interaction/agentMessage.ts b/packages/agent/src/tools/interaction/agentMessage.ts index 91e0afd..00a5ff4 100644 --- a/packages/agent/src/tools/interaction/agentMessage.ts +++ b/packages/agent/src/tools/interaction/agentMessage.ts @@ -1,10 +1,7 @@ import { z } from 'zod'; import { zodToJsonSchema } from 'zod-to-json-schema'; -import { - backgroundToolRegistry, - BackgroundToolStatus, -} from '../../core/backgroundTools.js'; +import { BackgroundToolStatus } from '../../core/backgroundTools.js'; import { Tool } from '../../core/types.js'; import { agentStates } from './agentStart.js'; @@ -54,7 +51,7 @@ export const agentMessageTool: Tool = { execute: async ( { instanceId, guidance, terminate }, - { logger }, + { logger, backgroundTools }, ): Promise => { logger.verbose( `Interacting with sub-agent ${instanceId}${guidance ? ' with guidance' : ''}${terminate ? ' with termination request' : ''}`, @@ -81,7 +78,7 @@ export const agentMessageTool: Tool = { agentState.completed = true; // Update background tool registry with terminated status - backgroundToolRegistry.updateToolStatus( + backgroundTools.updateToolStatus( instanceId, BackgroundToolStatus.TERMINATED, { diff --git a/packages/agent/src/tools/interaction/agentStart.ts b/packages/agent/src/tools/interaction/agentStart.ts index ec106f3..8b06295 100644 --- a/packages/agent/src/tools/interaction/agentStart.ts +++ b/packages/agent/src/tools/interaction/agentStart.ts @@ -2,10 +2,7 @@ import { v4 as uuidv4 } from 'uuid'; import { z } from 'zod'; import { zodToJsonSchema } from 'zod-to-json-schema'; -import { - backgroundToolRegistry, - BackgroundToolStatus, -} from '../../core/backgroundTools.js'; +import { BackgroundToolStatus } from '../../core/backgroundTools.js'; import { getDefaultSystemPrompt, AgentConfig, @@ -91,7 +88,7 @@ export const agentStartTool: Tool = { returns: returnSchema, returnsJsonSchema: zodToJsonSchema(returnSchema), execute: async (params, context) => { - const { logger, agentId } = context; + const { logger, backgroundTools } = context; // Validate parameters const { @@ -107,7 +104,7 @@ export const agentStartTool: Tool = { const instanceId = uuidv4(); // Register this agent with the background tool registry - backgroundToolRegistry.registerAgent(agentId || 'unknown', goal); + backgroundTools.registerAgent(goal); logger.verbose(`Registered agent with ID: ${instanceId}`); // Construct a well-structured prompt @@ -156,7 +153,7 @@ export const agentStartTool: Tool = { state.output = result.result; // Update background tool registry with completed status - backgroundToolRegistry.updateToolStatus( + backgroundTools.updateToolStatus( instanceId, BackgroundToolStatus.COMPLETED, { @@ -174,7 +171,7 @@ export const agentStartTool: Tool = { state.error = error instanceof Error ? error.message : String(error); // Update background tool registry with error status - backgroundToolRegistry.updateToolStatus( + backgroundTools.updateToolStatus( instanceId, BackgroundToolStatus.ERROR, { diff --git a/packages/agent/src/tools/interaction/agentTools.test.ts b/packages/agent/src/tools/interaction/agentTools.test.ts index 9b0531e..6e1c26f 100644 --- a/packages/agent/src/tools/interaction/agentTools.test.ts +++ b/packages/agent/src/tools/interaction/agentTools.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it, vi } from 'vitest'; +import { BackgroundTools } from '../../core/backgroundTools.js'; import { TokenTracker } from '../../core/tokens.js'; import { ToolContext } from '../../core/types.js'; import { MockLogger } from '../../utils/mockLogger.js'; @@ -28,6 +29,7 @@ const mockContext: ToolContext = { model: 'claude-3-7-sonnet-20250219', maxTokens: 4096, temperature: 0.7, + backgroundTools: new BackgroundTools('test'), }; describe('Agent Tools', () => { diff --git a/packages/agent/src/tools/interaction/subAgent.test.ts b/packages/agent/src/tools/interaction/subAgent.test.ts index 4b4df8e..6b0dff7 100644 --- a/packages/agent/src/tools/interaction/subAgent.test.ts +++ b/packages/agent/src/tools/interaction/subAgent.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it, vi } from 'vitest'; +import { BackgroundTools } from '../../core/backgroundTools.js'; import { TokenTracker } from '../../core/tokens.js'; import { ToolContext } from '../../core/types.js'; import { MockLogger } from '../../utils/mockLogger.js'; @@ -32,6 +33,7 @@ const mockContext: ToolContext = { model: 'claude-3-7-sonnet-20250219', maxTokens: 4096, temperature: 0.7, + backgroundTools: new BackgroundTools('test'), }; describe('subAgentTool', () => { diff --git a/packages/agent/src/tools/interaction/subAgent.ts b/packages/agent/src/tools/interaction/subAgent.ts index 3f66ae2..ac32616 100644 --- a/packages/agent/src/tools/interaction/subAgent.ts +++ b/packages/agent/src/tools/interaction/subAgent.ts @@ -2,7 +2,7 @@ import { z } from 'zod'; import { zodToJsonSchema } from 'zod-to-json-schema'; import { - backgroundToolRegistry, + BackgroundTools, BackgroundToolStatus, } from '../../core/backgroundTools.js'; import { @@ -69,7 +69,7 @@ export const subAgentTool: Tool = { returns: returnSchema, returnsJsonSchema: zodToJsonSchema(returnSchema), execute: async (params, context) => { - const { logger, agentId } = context; + const { logger, backgroundTools } = context; // Validate parameters const { @@ -81,12 +81,15 @@ export const subAgentTool: Tool = { } = parameterSchema.parse(params); // Register this sub-agent with the background tool registry - const subAgentId = backgroundToolRegistry.registerAgent( - agentId || 'unknown', - goal, - ); + const subAgentId = backgroundTools.registerAgent(goal); logger.verbose(`Registered sub-agent with ID: ${subAgentId}`); + const localContext = { + ...context, + workingDirectory: workingDirectory ?? context.workingDirectory, + backgroundTools: new BackgroundTools(`subAgent: ${goal}`), + }; + // Construct a well-structured prompt const prompt = [ `Description: ${description}`, @@ -108,13 +111,10 @@ export const subAgentTool: Tool = { }; try { - const result = await toolAgent(prompt, tools, config, { - ...context, - workingDirectory: workingDirectory ?? context.workingDirectory, - }); + const result = await toolAgent(prompt, tools, config, localContext); // Update background tool registry with completed status - backgroundToolRegistry.updateToolStatus( + backgroundTools.updateToolStatus( subAgentId, BackgroundToolStatus.COMPLETED, { @@ -127,13 +127,9 @@ export const subAgentTool: Tool = { return { response: result.result }; } catch (error) { // Update background tool registry with error status - backgroundToolRegistry.updateToolStatus( - subAgentId, - BackgroundToolStatus.ERROR, - { - error: error instanceof Error ? error.message : String(error), - }, - ); + backgroundTools.updateToolStatus(subAgentId, BackgroundToolStatus.ERROR, { + error: error instanceof Error ? error.message : String(error), + }); throw error; } diff --git a/packages/agent/src/tools/system/listBackgroundTools.test.ts b/packages/agent/src/tools/system/listBackgroundTools.test.ts index 5f9fddf..3b80dba 100644 --- a/packages/agent/src/tools/system/listBackgroundTools.test.ts +++ b/packages/agent/src/tools/system/listBackgroundTools.test.ts @@ -1,35 +1,8 @@ import { describe, expect, it, vi } from 'vitest'; -import { listBackgroundToolsTool } from './listBackgroundTools.js'; +import { BackgroundTools } from '../../core/backgroundTools.js'; -// Mock the entire background tools module -vi.mock('../../core/backgroundTools.js', () => { - return { - backgroundToolRegistry: { - getToolsByAgent: vi.fn().mockReturnValue([ - { - id: 'shell-1', - type: 'shell', - status: 'running', - startTime: new Date(Date.now() - 10000), - agentId: 'agent-1', - metadata: { command: 'ls -la' }, - }, - ]), - }, - BackgroundToolStatus: { - RUNNING: 'running', - COMPLETED: 'completed', - ERROR: 'error', - TERMINATED: 'terminated', - }, - BackgroundToolType: { - SHELL: 'shell', - BROWSER: 'browser', - AGENT: 'agent', - }, - }; -}); +import { listBackgroundToolsTool } from './listBackgroundTools.js'; describe('listBackgroundTools tool', () => { const mockLogger = { @@ -43,10 +16,10 @@ describe('listBackgroundTools tool', () => { it('should list background tools', async () => { const result = await listBackgroundToolsTool.execute({}, { logger: mockLogger as any, - agentId: 'agent-1', + backgroundTools: new BackgroundTools('test'), } as any); - expect(result.count).toEqual(1); - expect(result.tools).toHaveLength(1); + expect(result.count).toEqual(0); + expect(result.tools).toHaveLength(0); }); }); diff --git a/packages/agent/src/tools/system/listBackgroundTools.ts b/packages/agent/src/tools/system/listBackgroundTools.ts index 83eff8f..bc7608e 100644 --- a/packages/agent/src/tools/system/listBackgroundTools.ts +++ b/packages/agent/src/tools/system/listBackgroundTools.ts @@ -1,10 +1,7 @@ import { z } from 'zod'; import { zodToJsonSchema } from 'zod-to-json-schema'; -import { - backgroundToolRegistry, - BackgroundToolStatus, -} from '../../core/backgroundTools.js'; +import { BackgroundToolStatus } from '../../core/backgroundTools.js'; import { Tool } from '../../core/types.js'; const parameterSchema = z.object({ @@ -52,14 +49,14 @@ export const listBackgroundToolsTool: Tool = { execute: async ( { status = 'all', type = 'all', verbose = false }, - { logger, agentId }, + { logger, backgroundTools }, ): Promise => { logger.verbose( `Listing background tools with status: ${status}, type: ${type}, verbose: ${verbose}`, ); // Get all tools for this agent - const tools = backgroundToolRegistry.getToolsByAgent(agentId || 'unknown'); + const tools = backgroundTools.getTools(); // Filter by status if specified const filteredByStatus = diff --git a/packages/agent/src/tools/system/shellMessage.ts b/packages/agent/src/tools/system/shellMessage.ts index fc892ac..17655d9 100644 --- a/packages/agent/src/tools/system/shellMessage.ts +++ b/packages/agent/src/tools/system/shellMessage.ts @@ -1,10 +1,7 @@ import { z } from 'zod'; import { zodToJsonSchema } from 'zod-to-json-schema'; -import { - backgroundToolRegistry, - BackgroundToolStatus, -} from '../../core/backgroundTools.js'; +import { BackgroundToolStatus } from '../../core/backgroundTools.js'; import { Tool } from '../../core/types.js'; import { sleep } from '../../utils/sleep.js'; @@ -99,7 +96,7 @@ export const shellMessageTool: Tool = { execute: async ( { instanceId, stdin, signal, showStdIn, showStdout }, - { logger }, + { logger, backgroundTools }, ): Promise => { logger.verbose( `Interacting with shell process ${instanceId}${stdin ? ' with input' : ''}${signal ? ` with signal ${signal}` : ''}`, @@ -122,7 +119,7 @@ export const shellMessageTool: Tool = { processState.state.signaled = true; // Update background tool registry if signal failed - backgroundToolRegistry.updateToolStatus( + backgroundTools.updateToolStatus( instanceId, BackgroundToolStatus.ERROR, { @@ -142,7 +139,7 @@ export const shellMessageTool: Tool = { signal === 'SIGKILL' || signal === 'SIGINT' ) { - backgroundToolRegistry.updateToolStatus( + backgroundTools.updateToolStatus( instanceId, BackgroundToolStatus.TERMINATED, { @@ -151,7 +148,7 @@ export const shellMessageTool: Tool = { }, ); } else { - backgroundToolRegistry.updateToolStatus( + backgroundTools.updateToolStatus( instanceId, BackgroundToolStatus.RUNNING, { diff --git a/packages/agent/src/tools/system/shellStart.ts b/packages/agent/src/tools/system/shellStart.ts index fa8e36d..c98c7e7 100644 --- a/packages/agent/src/tools/system/shellStart.ts +++ b/packages/agent/src/tools/system/shellStart.ts @@ -4,10 +4,7 @@ import { v4 as uuidv4 } from 'uuid'; import { z } from 'zod'; import { zodToJsonSchema } from 'zod-to-json-schema'; -import { - backgroundToolRegistry, - BackgroundToolStatus, -} from '../../core/backgroundTools.js'; +import { BackgroundToolStatus } from '../../core/backgroundTools.js'; import { Tool } from '../../core/types.js'; import { errorToString } from '../../utils/errorToString.js'; @@ -102,7 +99,7 @@ export const shellStartTool: Tool = { showStdIn = false, showStdout = false, }, - { logger, workingDirectory, agentId }, + { logger, workingDirectory, backgroundTools }, ): Promise => { if (showStdIn) { logger.info(`Command input: ${command}`); @@ -115,7 +112,7 @@ export const shellStartTool: Tool = { const instanceId = uuidv4(); // Register this shell process with the background tool registry - backgroundToolRegistry.registerShell(agentId || 'unknown', command); + backgroundTools.registerShell(command); let hasResolved = false; @@ -164,7 +161,7 @@ export const shellStartTool: Tool = { processState.state.completed = true; // Update background tool registry with error status - backgroundToolRegistry.updateToolStatus( + backgroundTools.updateToolStatus( instanceId, BackgroundToolStatus.ERROR, { @@ -198,7 +195,7 @@ export const shellStartTool: Tool = { code === 0 ? BackgroundToolStatus.COMPLETED : BackgroundToolStatus.ERROR; - backgroundToolRegistry.updateToolStatus(instanceId, status, { + backgroundTools.updateToolStatus(instanceId, status, { exitCode: code, signaled: signal !== null, }); diff --git a/packages/agent/src/utils/logger.ts b/packages/agent/src/utils/logger.ts index bf38316..8f16f83 100644 --- a/packages/agent/src/utils/logger.ts +++ b/packages/agent/src/utils/logger.ts @@ -37,7 +37,7 @@ export const BasicLoggerStyler = { : prefix, showPrefix: (_level: LogLevel): boolean => { // Show prefix for all log levels - return true; + return false; }, }; diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 718d89d..204485d 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,3 +1,27 @@ +# [mycoder-v1.1.1](https://github.com/drivecore/mycoder/compare/mycoder-v1.1.0...mycoder-v1.1.1) (2025-03-12) + +### Bug Fixes + +- remove userWarning option from docs and Github Action. ([35617c1](https://github.com/drivecore/mycoder/commit/35617c19a4a03ba5c170b93d035bdf99ddb81544)) + +# [mycoder-v1.1.0](https://github.com/drivecore/mycoder/compare/mycoder-v1.0.0...mycoder-v1.1.0) (2025-03-12) + +### Bug Fixes + +- implement resource cleanup to prevent CLI hanging issue ([d33e729](https://github.com/drivecore/mycoder/commit/d33e7298686a30661ee8b36f2fdffb16f5f3da71)), closes [#141](https://github.com/drivecore/mycoder/issues/141) +- llm choice working well for openai, anthropic and ollama ([68d34ab](https://github.com/drivecore/mycoder/commit/68d34abf8a73ed533a072359ce334a9364753425)) +- remove unreliable init command and createDefaultConfigFile function ([5559567](https://github.com/drivecore/mycoder/commit/5559567d1986e828983f5975495bee89fcd91772)), closes [#225](https://github.com/drivecore/mycoder/issues/225) +- replace @semantic-release/npm with @anolilab/semantic-release-pnpm to properly resolve workspace references ([bacb51f](https://github.com/drivecore/mycoder/commit/bacb51f637f2b2d3b1039bdfdbd33e3d704b6cde)) + +### Features + +- add git and gh CLI tools availability check ([8996f36](https://github.com/drivecore/mycoder/commit/8996f3609d3d13a62dd9943bfe2e846508a70336)), closes [#217](https://github.com/drivecore/mycoder/issues/217) +- add Ollama configuration options ([d5c3a96](https://github.com/drivecore/mycoder/commit/d5c3a96ce9463c98504c2a346796400df36bf3b0)) +- **cli:** Add checking for git and gh CLI tools in GitHub mode ([5443185](https://github.com/drivecore/mycoder/commit/54431854e1e02de2a3c6bf993b114993739dcca1)), closes [#217](https://github.com/drivecore/mycoder/issues/217) +- **llm:** add OpenAI support to LLM abstraction ([7bda811](https://github.com/drivecore/mycoder/commit/7bda811658e15b8dd41135cd9b2b90e9ea925e15)) +- **refactor:** agent ([a2f59c2](https://github.com/drivecore/mycoder/commit/a2f59c2f51643a44d6e1ff0c16b319deb1adc3f2)) +- Replace config CLI commands with config file-based approach ([#215](https://github.com/drivecore/mycoder/issues/215)) ([8dffcef](https://github.com/drivecore/mycoder/commit/8dffcef10c123c05ef6970c465c4d8b3f0475622)) + # mycoder-v1.0.0 (2025-03-11) ### Bug Fixes diff --git a/packages/cli/package.json b/packages/cli/package.json index 6f7a6c9..79374fb 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "mycoder", "description": "A command line tool using agent that can do arbitrary tasks, including coding tasks", - "version": "1.0.1", + "version": "1.1.1", "type": "module", "bin": "./bin/cli.js", "main": "./dist/index.js", diff --git a/packages/cli/src/commands/$default.ts b/packages/cli/src/commands/$default.ts index cc57b93..3680d8c 100644 --- a/packages/cli/src/commands/$default.ts +++ b/packages/cli/src/commands/$default.ts @@ -14,6 +14,7 @@ import { DEFAULT_CONFIG, AgentConfig, ModelProvider, + BackgroundTools, } from 'mycoder-agent'; import { TokenTracker } from 'mycoder-agent/dist/core/tokens.js'; @@ -208,6 +209,7 @@ export const command: CommandModule = { model: config.model, maxTokens: config.maxTokens, temperature: config.temperature, + backgroundTools: new BackgroundTools('mainAgent'), }); const output =