diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f58f07..fab70a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,9 +27,15 @@ jobs: - name: Install dependencies run: pnpm install --frozen-lockfile - + - name: Build run: pnpm build:ci + - name: Install browsers + run: pnpm exec playwright install --with-deps chromium + - name: Test run: pnpm test + + - name: Lint + run: pnpm lint \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 14708d8..643b347 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # mycoder +## 0.1.0 + +### Minor Changes + +- Add support for browsing the web + ## 0.0.23 ### Patch Changes diff --git a/package.json b/package.json index 3147980..b047d6a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mycoder", "description": "A command line tool using agent that can do arbitrary tasks, including coding tasks", - "version": "0.0.23", + "version": "0.1.0", "type": "module", "bin": "./bin/cli.js", "main": "./dist/index.js", diff --git a/src/tools/browser/BrowserAutomation.ts b/src/tools/browser/BrowserAutomation.ts index f344e28..52f3b83 100644 --- a/src/tools/browser/BrowserAutomation.ts +++ b/src/tools/browser/BrowserAutomation.ts @@ -16,7 +16,7 @@ export class BrowserAutomation { return BrowserAutomation.instance; } - async createSession(headless: boolean = false) { + async createSession(headless: boolean = true) { const session = await this.browserManager.createSession({ headless }); const pageController = new PageController(session.page); diff --git a/src/tools/browser/BrowserManager.ts b/src/tools/browser/BrowserManager.ts index e272f52..9d1fff4 100644 --- a/src/tools/browser/BrowserManager.ts +++ b/src/tools/browser/BrowserManager.ts @@ -10,7 +10,7 @@ import { export class BrowserManager { private sessions: Map = new Map(); private readonly defaultConfig: BrowserConfig = { - headless: false, + headless: true, defaultTimeout: 30000, }; diff --git a/src/tools/browser/PageController.ts b/src/tools/browser/PageController.ts index 65b83ac..5a894de 100644 --- a/src/tools/browser/PageController.ts +++ b/src/tools/browser/PageController.ts @@ -5,6 +5,7 @@ import { BrowserError, BrowserErrorCode, } from './types.js'; +import { errorToString } from '../../utils/errorToString.js'; export class PageController { constructor(private page: Page) {} @@ -27,13 +28,14 @@ export class PageController { } } - private validateSelector(selector: string, type: SelectorType): void { + private validateSelector(selector: string, _type: SelectorType): void { if (!selector) { throw new BrowserError( 'Invalid selector: empty string', BrowserErrorCode.SELECTOR_INVALID, ); } + // TODO: Add more validation } async waitForSelector( @@ -51,7 +53,7 @@ export class PageController { }); } catch (error) { throw new BrowserError( - `Failed to find element: ${error}`, + `Failed to find element: ${errorToString(error)}`, BrowserErrorCode.ELEMENT_NOT_FOUND, error, ); @@ -67,7 +69,7 @@ export class PageController { await locator.click({ timeout: options.timeout }); } catch (error) { throw new BrowserError( - `Failed to click element: ${error}`, + `Failed to click element: ${errorToString(error)}`, BrowserErrorCode.SELECTOR_ERROR, error, ); @@ -87,7 +89,7 @@ export class PageController { await locator.fill(text, { timeout: options.timeout }); } catch (error) { throw new BrowserError( - `Failed to type text: ${error}`, + `Failed to type text: ${errorToString(error)}`, BrowserErrorCode.SELECTOR_ERROR, error, ); @@ -106,7 +108,7 @@ export class PageController { return (await locator.textContent()) || ''; } catch (error) { throw new BrowserError( - `Failed to get text: ${error}`, + `Failed to get text: ${errorToString(error)}`, BrowserErrorCode.SELECTOR_ERROR, error, ); diff --git a/src/tools/browser/browseMessage.ts b/src/tools/browser/browseMessage.ts index 0c0ec39..aa69bb3 100644 --- a/src/tools/browser/browseMessage.ts +++ b/src/tools/browser/browseMessage.ts @@ -2,6 +2,7 @@ import { Tool } from '../../core/types.js'; import { z } from 'zod'; import { zodToJsonSchema } from 'zod-to-json-schema'; import { browserSessions, type BrowserAction, SelectorType } from './types.js'; +import { errorToString } from '../../utils/errorToString.js'; // Schema for browser action const browserActionSchema = z @@ -141,7 +142,7 @@ export const browseMessageTool: Tool = { logger.error('Browser action failed:', { error }); return { status: 'error', - error: error instanceof Error ? error.message : String(error), + error: errorToString(error), }; } }, diff --git a/src/tools/browser/browseStart.ts b/src/tools/browser/browseStart.ts index d3c008f..5925678 100644 --- a/src/tools/browser/browseStart.ts +++ b/src/tools/browser/browseStart.ts @@ -4,6 +4,7 @@ import { zodToJsonSchema } from 'zod-to-json-schema'; import { v4 as uuidv4 } from 'uuid'; import { chromium } from '@playwright/test'; import { browserSessions } from './types.js'; +import { errorToString } from '../../utils/errorToString.js'; const parameterSchema = z.object({ url: z.string().url().optional().describe('Initial URL to navigate to'), @@ -91,11 +92,11 @@ export const browseStartTool: Tool = { content: content || undefined, }; } catch (error) { - logger.error(`Failed to start browser: ${error}`); + logger.error(`Failed to start browser: ${errorToString(error)}`); return { instanceId: '', status: 'error', - error: error instanceof Error ? error.message : String(error), + error: errorToString(error), }; } }, diff --git a/src/tools/system/shellStart.ts b/src/tools/system/shellStart.ts index c4d1db9..6512c73 100644 --- a/src/tools/system/shellStart.ts +++ b/src/tools/system/shellStart.ts @@ -169,7 +169,7 @@ export const shellStartTool: Tool = { stdout: '', stderr: '', exitCode: 1, - error: error instanceof Error ? error.message : String(error), + error: errorToString(error), }); } }); diff --git a/src/utils/versionCheck.ts b/src/utils/versionCheck.ts index 3d38467..ee844cb 100644 --- a/src/utils/versionCheck.ts +++ b/src/utils/versionCheck.ts @@ -7,6 +7,7 @@ import { getSettingsDir } from '../settings/settings.js'; import * as fsPromises from 'fs/promises'; import * as fs from 'fs'; import * as semver from 'semver'; +import { errorToString } from './errorToString.js'; const require = createRequire(import.meta.url); const logger = new Logger({ name: 'version-check' }); @@ -76,19 +77,13 @@ export async function checkForUpdates(): Promise { return fsPromises.writeFile(versionFilePath, latestVersion, 'utf8'); }) .catch((error) => { - logger.warn( - 'Error fetching latest version:', - error instanceof Error ? error.message : String(error), - ); + logger.warn('Error fetching latest version:', errorToString(error)); }); return null; } catch (error) { // Log error but don't throw to handle gracefully - logger.warn( - 'Error checking for updates:', - error instanceof Error ? error.message : String(error), - ); + logger.warn('Error checking for updates:', errorToString(error)); return null; } }