From 210fd567694aeab4124de734319f282242a9c0e8 Mon Sep 17 00:00:00 2001 From: Shannon Code Date: Thu, 24 Oct 2024 00:25:47 -0400 Subject: [PATCH 01/14] add .cursor files to capture current state and outline new features --- .cursor/current_status.md | 29 +++++++ .cursor/errors_resolutions.md | 8 ++ .cursor/instructions.md | 16 ++++ .cursor/plan.md | 144 ++++++++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+) create mode 100644 .cursor/current_status.md create mode 100644 .cursor/errors_resolutions.md create mode 100644 .cursor/instructions.md create mode 100644 .cursor/plan.md diff --git a/.cursor/current_status.md b/.cursor/current_status.md new file mode 100644 index 0000000..b560e74 --- /dev/null +++ b/.cursor/current_status.md @@ -0,0 +1,29 @@ +# Current Status + +## Iteration 1: Project Evaluation + +1. Completed initial project structure analysis +2. Identified key components and their purposes: + - Main process (`src/main/main.ts`) + - Renderer process (`src/renderer/App.tsx`) + - State management (`src/main/store/create.ts`) + - AI agent logic (`src/main/store/runAgent.ts`) +3. Reviewed existing features: + - Direct computer control by Claude 3.5 Sonnet + - Real-time execution of AI-generated commands + - Simple Electron-based user interface + - Support for MacOS (with theoretical support for Windows and Linux) + - Primary display interaction + - Emergency stop functionality +4. Identified areas for enhancement as per the project plan: + - Persistent settings + - System prompt configuration + - Enhanced logging with images + - Plugin system + - Window state persistence + - Session management + - Configurable tools system +5. Next steps: + - Begin implementation of persistent settings + - Set up development environment for new features + - Create a more detailed roadmap for feature implementation diff --git a/.cursor/errors_resolutions.md b/.cursor/errors_resolutions.md new file mode 100644 index 0000000..864a252 --- /dev/null +++ b/.cursor/errors_resolutions.md @@ -0,0 +1,8 @@ +# Errors and Resolutions + +**Top Mistakes to Avoid:** + +1. **Always... + + +# Error # 1... \ No newline at end of file diff --git a/.cursor/instructions.md b/.cursor/instructions.md new file mode 100644 index 0000000..b170713 --- /dev/null +++ b/.cursor/instructions.md @@ -0,0 +1,16 @@ +Begin building out the project defined in @plan.md +# Every iteration, be sure to update the @current_status.md document to capture our place in the development cycle +# When errors are encountered, document them and their resolution in @errors_resolutions.md if multiple attempts to fix take place, be sure to collect all attempts, the new reasoning, and ultimately the final resolution. + +# NOTE: pay close attention to directory structure, @plan.md is located in the project root. Any bootstrapping that takes place should understand where root is, and where any client / serverside applications are. Keep Dockerfile up to date. +# NOTE: this project should be usable within Docker throughout the process, so always keep a Dockerfile and a compose file up to date + +# IMPORTANT: record achievements in @current_status.md +# IMPORTANT: @current_status.md is append only +# IMPORTANT: @errors_resolutions.md is append only +# IMPORTANT: @plan.md is read only +# IMPORTANT: @instructions.md is read only + +# IMPORTANT: every iteration we should be able to run our docker and have it work based on the stage of the project. Deliver Value every iteration. + +# IMPORTANT: Any Docker configurations should ignore local package-lock.json files and node_modules directories. This ensures consistency across different development environments and the Docker container. Update .dockerignore and Dockerfile accordingly. diff --git a/.cursor/plan.md b/.cursor/plan.md new file mode 100644 index 0000000..f3c3074 --- /dev/null +++ b/.cursor/plan.md @@ -0,0 +1,144 @@ +# Agent.exe Project Plan + +## Project Overview + +Agent.exe is an Electron-based application that allows Claude 3.5 Sonnet, an AI model, to control a user's local computer directly. The project aims to showcase and utilize Claude's computer use capabilities in a lightweight, user-friendly interface. + +## Project Directory + +``` +Agent.exe/ +Agent.exe/ +├── .cursor/ # Directory for cursor-related files +│ ├── instructions.md # Instructions for the development process +│ ├── current_status.md # Current status of the project +│ └── plan.md # Project plan and roadmap +├── .erb/ # Electron React Boilerplate configurations +│ └── configs/ # Webpack and other build configurations +│ └── webpack.config.main.dev.ts # Webpack config for main process development +├── assets/ # Static assets like images and icons +├── release/ # Build output directory +│ └── app/ # Application package directory +│ └── package.json # Package configuration for the built app +├── src/ # Source code directory +│ ├── main/ # Main process code +│ │ ├── main.ts # Entry point for the main process +│ │ ├── menu.ts # Application menu configuration +│ │ ├── preload.ts # Preload script for renderer process +│ │ └── store/ # State management for main process +│ │ ├── create.ts # Store creation and configuration +│ │ ├── runAgent.ts # Logic for running the AI agent +│ │ └── types.ts # TypeScript type definitions +│ └── renderer/ # Renderer process code +│ ├── App.tsx # Main React component +│ ├── index.ejs # HTML template for the app +│ └── RunHistory.tsx # Component for displaying run history +├── .editorconfig # Editor configuration for consistent coding styles +├── .env # Environment variables (not tracked in git) +├── .eslintignore # Files to be ignored by ESLint +├── .eslintrc # ESLint configuration +├── .gitignore # Git ignore file +├── package.json # Node.js dependencies and scripts +├── README.md # Project documentation and overview +└── tsconfig.json # TypeScript configuration +``` + +## Current Features + +1. Direct computer control by Claude 3.5 Sonnet +2. Real-time execution of AI-generated commands +3. Simple Electron-based user interface +4. Support for MacOS (with theoretical support for Windows and Linux) +5. Primary display interaction +6. Emergency stop functionality + +## Planned Enhancements + +### 1. Persistent Settings + +- Implement a settings storage system that saves user preferences across application restarts +- Utilize Electron's `electron-store` or a similar library for efficient local storage + +### 2. System Prompt Configuration + +- Add a new tab or section in the UI for users to input and edit system prompts +- Store and load system prompts as part of the persistent settings + +### 3. Enhanced Logging with Images + +- Modify the `RunHistory` component to include image support +- Capture and display screenshots of actions performed by the AI +- Implement an image storage and retrieval system + +### 4. Plugin System + +- Design and implement a plugin architecture to extend the application's functionality +- Create a plugin loader and manager +- Develop a standardized plugin API for third-party developers + +### 5. Window State Persistence + +- Save and restore the application window's size and position between restarts +- Utilize Electron's `electron-window-state` or a custom implementation + +### 6. Session Management + +- Implement functionality to save the current message stack as a "session" +- Create a session loading mechanism +- Design a user interface for managing (saving, loading, deleting) sessions + +### 7. Configurable Tools System + +- Develop a tool configuration interface in the settings +- Implement a tool management system that can launch, close, and manage tool state +- Create a screenshot masking system to focus on the active tool +- Pass tool context to the AI model + +## Implementation Plan + +### 1. Persistent Settings + +1. Install `electron-store` or a similar library +2. Create a `settings.ts` file to manage application settings +3. Modify the main process to load and save settings +4. Update the renderer process to reflect and modify settings + +### 2. System Prompt Configuration + +1. Add a new React component for system prompt input +2. Modify the store to include system prompt state +3. Update the AI interaction logic to incorporate the system prompt + +### 3. Enhanced Logging with Images + +1. Modify the `RunHistory` component to support image display +2. Update the `runAgent` function to capture screenshots after each action +3. Implement an image storage system using the file system or a lightweight database + +### 4. Plugin System + +1. Design the plugin API and architecture +2. Create a plugin loader in the main process +3. Implement a plugin manager to handle plugin lifecycle +4. Develop a UI for enabling/disabling plugins + +### 5. Window State Persistence + +1. Install `electron-window-state` or implement a custom solution +2. Modify the main process to save and restore window state +3. Update the `createWindow` function to use the saved state + +### 6. Session Management + +1. Design the session data structure +2. Implement save and load functions for sessions +3. Create a UI for session management (list, save, load, delete) +4. Modify the store to handle session state + +### 7. Configurable Tools System + +1. Design the tool configuration data structure +2. Create a UI for tool configuration in the settings +3. Implement a tool management system in the main process +4. Modify the `runAgent` function to handle tool context and management +5. Develop a screenshot masking system for active tools From 06762c3b3e2707d68089261352598c1fda4f93b0 Mon Sep 17 00:00:00 2001 From: Shannon Code Date: Thu, 24 Oct 2024 00:34:32 -0400 Subject: [PATCH 02/14] no docker --- .cursor/instructions.md | 7 ++----- src/renderer/index.tsx | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.cursor/instructions.md b/.cursor/instructions.md index b170713..82d4c91 100644 --- a/.cursor/instructions.md +++ b/.cursor/instructions.md @@ -2,8 +2,7 @@ Begin building out the project defined in @plan.md # Every iteration, be sure to update the @current_status.md document to capture our place in the development cycle # When errors are encountered, document them and their resolution in @errors_resolutions.md if multiple attempts to fix take place, be sure to collect all attempts, the new reasoning, and ultimately the final resolution. -# NOTE: pay close attention to directory structure, @plan.md is located in the project root. Any bootstrapping that takes place should understand where root is, and where any client / serverside applications are. Keep Dockerfile up to date. -# NOTE: this project should be usable within Docker throughout the process, so always keep a Dockerfile and a compose file up to date +# NOTE: pay close attention to directory structure, @plan.md is located in the project root. Any bootstrapping that takes place should understand where root is, and where any client / serverside applications are. # IMPORTANT: record achievements in @current_status.md # IMPORTANT: @current_status.md is append only @@ -11,6 +10,4 @@ Begin building out the project defined in @plan.md # IMPORTANT: @plan.md is read only # IMPORTANT: @instructions.md is read only -# IMPORTANT: every iteration we should be able to run our docker and have it work based on the stage of the project. Deliver Value every iteration. - -# IMPORTANT: Any Docker configurations should ignore local package-lock.json files and node_modules directories. This ensures consistency across different development environments and the Docker container. Update .dockerignore and Dockerfile accordingly. +# IMPORTANT: every iteration we should be able to run our application and have it work based on the stage of the project. Deliver Value every iteration. diff --git a/src/renderer/index.tsx b/src/renderer/index.tsx index 064a057..b9d558d 100644 --- a/src/renderer/index.tsx +++ b/src/renderer/index.tsx @@ -10,4 +10,4 @@ window.electron.ipcRenderer.once('ipc-example', (arg) => { // eslint-disable-next-line no-console console.log(arg); }); -window.electron.ipcRenderer.sendMessage('ipc-example', ['ping']); +window.electron.ipcRenderer.sendMessage('ipc-example', ['ping']); \ No newline at end of file From b20657414f19a99f45c4157885919c5223046a8b Mon Sep 17 00:00:00 2001 From: Shannon Code Date: Thu, 24 Oct 2024 00:47:27 -0400 Subject: [PATCH 03/14] cleanup plan and add Notepad helper for this app --- .cursor/App.notepad | 39 +++++++++++++++++++++++++++++++++++++++ .cursor/plan.md | 8 +++++--- 2 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 .cursor/App.notepad diff --git a/.cursor/App.notepad b/.cursor/App.notepad new file mode 100644 index 0000000..2a07843 --- /dev/null +++ b/.cursor/App.notepad @@ -0,0 +1,39 @@ +These files represent the entire application + +Agent.exe/ +├── .cursor/ # Directory for cursor-related files +│ ├── @instructions.md # Instructions for the development process +│ ├── @current_status.md # Current status of the project +│ └── @plan.md # Project plan and roadmap +├── .erb/ # Electron React Boilerplate configurations +│ └── configs/ # Webpack and other build configurations +│ └── @webpack.config.main.dev.ts # Webpack config for main process development +├── assets/ # Static assets like images and icons +├── release/ # Build output directory +│ └── app/ # Application package directory +│ └── @package.json # Package configuration for the built app +├── src/ # Source code directory +│ ├── main/ # Main process code +│ │ ├── @main.ts # Entry point for the main process +│ │ ├── @menu.ts # Application menu configuration +│ │ ├── @preload.ts # Preload script for renderer process +│ │ └── store/ # State management for main process +│ │ ├── @create.ts # Store creation and configuration +│ │ ├── @runAgent.ts # Logic for running the AI agent +│ │ └── @types.ts # TypeScript type definitions +│ └── renderer/ # Renderer process code +│ ├── @App.tsx # Main React component +│ ├── @index.ejs # HTML template for the app +│ ├── @index.tsx # Entry point for the renderer process +│ ├── @RunHistory.tsx # Component for displaying run history +│ ├── @global.d.ts # Global type declarations +│ └── hooks/ # Custom React hooks +│ └── @useStore.ts # Hook for accessing the Zustand store +├── .editorconfig # Editor configuration for consistent coding styles +├── .env # Environment variables (not tracked in git) +├── .eslintignore # Files to be ignored by ESLint +├── .eslintrc # ESLint configuration +├── .gitignore # Git ignore file +├── @package.json # Node.js dependencies and scripts +├── @README.md # Project documentation and overview +└── tsconfig.json # TypeScript configuration \ No newline at end of file diff --git a/.cursor/plan.md b/.cursor/plan.md index f3c3074..9106a98 100644 --- a/.cursor/plan.md +++ b/.cursor/plan.md @@ -8,7 +8,6 @@ Agent.exe is an Electron-based application that allows Claude 3.5 Sonnet, an AI ``` Agent.exe/ -Agent.exe/ ├── .cursor/ # Directory for cursor-related files │ ├── instructions.md # Instructions for the development process │ ├── current_status.md # Current status of the project @@ -23,7 +22,6 @@ Agent.exe/ ├── src/ # Source code directory │ ├── main/ # Main process code │ │ ├── main.ts # Entry point for the main process -│ │ ├── menu.ts # Application menu configuration │ │ ├── preload.ts # Preload script for renderer process │ │ └── store/ # State management for main process │ │ ├── create.ts # Store creation and configuration @@ -32,7 +30,11 @@ Agent.exe/ │ └── renderer/ # Renderer process code │ ├── App.tsx # Main React component │ ├── index.ejs # HTML template for the app -│ └── RunHistory.tsx # Component for displaying run history +│ ├── index.tsx # Entry point for the renderer process +│ ├── RunHistory.tsx # Component for displaying run history +│ ├── global.d.ts # Global type declarations +│ └── hooks/ # Custom React hooks +│ └── useStore.ts # Hook for accessing the Zustand store ├── .editorconfig # Editor configuration for consistent coding styles ├── .env # Environment variables (not tracked in git) ├── .eslintignore # Files to be ignored by ESLint From d71a9a80b67bd9be01388da82e5f7030839035a7 Mon Sep 17 00:00:00 2001 From: Shannon Code Date: Thu, 24 Oct 2024 01:38:09 -0400 Subject: [PATCH 04/14] app settings --- .cursor/current_status.md | 11 +++++++++++ src/main/settings.ts | 28 ++++++++++++++++++++++++++++ src/main/store/create.ts | 16 +++++++++++----- src/renderer/App.tsx | 15 ++++++--------- 4 files changed, 56 insertions(+), 14 deletions(-) create mode 100644 src/main/settings.ts diff --git a/.cursor/current_status.md b/.cursor/current_status.md index b560e74..a4ea2d7 100644 --- a/.cursor/current_status.md +++ b/.cursor/current_status.md @@ -27,3 +27,14 @@ - Begin implementation of persistent settings - Set up development environment for new features - Create a more detailed roadmap for feature implementation + +## Iteration 2: Persistent Settings Implementation + +1. Installed `electron-store` library for efficient local storage +2. Created `src/main/settings.ts` to manage application settings +3. Modified `src/main/store/create.ts` to use persistent settings +4. Updated `src/renderer/App.tsx` to utilize persistent settings +5. Implemented saving and loading of `instructions` and `fullyAuto` settings +6. Next steps: + - Test the persistent settings functionality + - Move on to the next enhancement: System Prompt Configuration diff --git a/src/main/settings.ts b/src/main/settings.ts new file mode 100644 index 0000000..6d762eb --- /dev/null +++ b/src/main/settings.ts @@ -0,0 +1,28 @@ +import Store from 'electron-store'; +import { AppState } from './store/types'; + +interface SettingsSchema { + instructions: string | null; + fullyAuto: boolean; +} + +const store = new Store({ + defaults: { + instructions: null, + fullyAuto: true, + }, +}); + +export const loadSettings = (): Partial => ({ + instructions: store.get('instructions'), + fullyAuto: store.get('fullyAuto'), +}); + +export const saveSettings = (state: Partial) => { + if (state.instructions !== undefined) { + store.set('instructions', state.instructions); + } + if (state.fullyAuto !== undefined) { + store.set('fullyAuto', state.fullyAuto); + } +}; diff --git a/src/main/store/create.ts b/src/main/store/create.ts index 768c8fb..c12e6bf 100644 --- a/src/main/store/create.ts +++ b/src/main/store/create.ts @@ -2,19 +2,25 @@ import { createStore } from 'zustand/vanilla'; import { createDispatch } from 'zutron/main'; import { AppState } from './types'; import { runAgent } from './runAgent'; +import { loadSettings, saveSettings } from '../settings'; + +const initialSettings = loadSettings(); export const store = createStore((set, get) => ({ - instructions: 'find flights from seattle to sf for next tuesday to thursday', - fullyAuto: true, // renamed and changed default to true + instructions: initialSettings.instructions ?? 'find flights from seattle to sf for next tuesday to thursday', + fullyAuto: initialSettings.fullyAuto ?? true, running: false, error: null, runHistory: [], RUN_AGENT: async () => runAgent(set, get), STOP_RUN: () => set({ running: false }), - SET_INSTRUCTIONS: (instructions) => set({ instructions }), + SET_INSTRUCTIONS: (instructions) => { + set({ instructions }); + saveSettings({ instructions }); + }, SET_FULLY_AUTO: (fullyAuto) => { - // renamed from SET_HUMAN_SUPERVISED - set({ fullyAuto: fullyAuto ?? true }); // changed default to true + set({ fullyAuto }); + saveSettings({ fullyAuto }); }, CLEAR_HISTORY: () => set({ runHistory: [] }), })); diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index a981f9d..712f0e9 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -47,6 +47,11 @@ function Main() { } }; + const handleFullyAutoChange = (e: React.ChangeEvent) => { + const newValue = e.target.checked; + dispatch({ type: 'SET_FULLY_AUTO', payload: newValue }); + }; + return ( { - toast({ - description: - "Whoops, automatic mode isn't actually implemented yet. 😬", - status: 'info', - duration: 3000, - isClosable: true, - }); - }} + onChange={handleFullyAutoChange} /> Full Auto From dd2983f2c6ed2463e8696a448770da42fe102c22 Mon Sep 17 00:00:00 2001 From: Shannon Code Date: Thu, 24 Oct 2024 01:47:10 -0400 Subject: [PATCH 05/14] update system prompt --- .cursor/current_status.md | 14 ++++ src/main/settings.ts | 6 ++ src/main/store/create.ts | 7 +- src/main/store/runAgent.ts | 8 +-- src/main/store/types.ts | 3 +- src/renderer/App.tsx | 118 +++++++++++++++++++--------------- src/renderer/SystemPrompt.tsx | 47 ++++++++++++++ 7 files changed, 145 insertions(+), 58 deletions(-) create mode 100644 src/renderer/SystemPrompt.tsx diff --git a/.cursor/current_status.md b/.cursor/current_status.md index a4ea2d7..1209e75 100644 --- a/.cursor/current_status.md +++ b/.cursor/current_status.md @@ -38,3 +38,17 @@ 6. Next steps: - Test the persistent settings functionality - Move on to the next enhancement: System Prompt Configuration + +## Iteration 3: System Prompt Configuration + +1. Updated `src/main/store/types.ts` to include systemPrompt in AppState +2. Modified `src/main/settings.ts` to handle systemPrompt persistence +3. Updated `src/main/store/create.ts` to include systemPrompt in the store +4. Created new `src/renderer/SystemPrompt.tsx` component for editing system prompts +5. Updated `src/renderer/App.tsx` to include the SystemPrompt component as a tab +6. Implemented a resizable textarea for editing the system prompt +7. Added a "Apply Default Prompt" button to easily set a predefined system prompt +8. Modified `src/main/store/runAgent.ts` to incorporate systemPrompt in AI interactions +9. Tested the system prompt configuration functionality +10. Next steps: + - Move on to the next enhancement: Enhanced Logging with Images diff --git a/src/main/settings.ts b/src/main/settings.ts index 6d762eb..d673de0 100644 --- a/src/main/settings.ts +++ b/src/main/settings.ts @@ -4,18 +4,21 @@ import { AppState } from './store/types'; interface SettingsSchema { instructions: string | null; fullyAuto: boolean; + systemPrompt: string; } const store = new Store({ defaults: { instructions: null, fullyAuto: true, + systemPrompt: '', }, }); export const loadSettings = (): Partial => ({ instructions: store.get('instructions'), fullyAuto: store.get('fullyAuto'), + systemPrompt: store.get('systemPrompt'), }); export const saveSettings = (state: Partial) => { @@ -25,4 +28,7 @@ export const saveSettings = (state: Partial) => { if (state.fullyAuto !== undefined) { store.set('fullyAuto', state.fullyAuto); } + if (state.systemPrompt !== undefined) { + store.set('systemPrompt', state.systemPrompt); + } }; diff --git a/src/main/store/create.ts b/src/main/store/create.ts index c12e6bf..0e2daa8 100644 --- a/src/main/store/create.ts +++ b/src/main/store/create.ts @@ -7,8 +7,9 @@ import { loadSettings, saveSettings } from '../settings'; const initialSettings = loadSettings(); export const store = createStore((set, get) => ({ - instructions: initialSettings.instructions ?? 'find flights from seattle to sf for next tuesday to thursday', + instructions: initialSettings.instructions ?? '', fullyAuto: initialSettings.fullyAuto ?? true, + systemPrompt: initialSettings.systemPrompt ?? '', // Add this line running: false, error: null, runHistory: [], @@ -22,6 +23,10 @@ export const store = createStore((set, get) => ({ set({ fullyAuto }); saveSettings({ fullyAuto }); }, + SET_SYSTEM_PROMPT: (systemPrompt) => { // Add this function + set({ systemPrompt }); + saveSettings({ systemPrompt }); + }, CLEAR_HISTORY: () => set({ runHistory: [] }), })); diff --git a/src/main/store/runAgent.ts b/src/main/store/runAgent.ts index e45d65e..fadd1ed 100644 --- a/src/main/store/runAgent.ts +++ b/src/main/store/runAgent.ts @@ -78,6 +78,7 @@ const mapFromAiSpace = (x: number, y: number) => { const promptForAction = async ( runHistory: BetaMessageParam[], + systemPrompt: string ): Promise => { // Strip images from all but the last message const historyWithoutImages = runHistory.map((msg, index) => { @@ -102,6 +103,8 @@ const promptForAction = async ( const message = await anthropic.beta.messages.create({ model: 'claude-3-5-sonnet-20241022', max_tokens: 1024, + system: systemPrompt, // Add this line + messages: historyWithoutImages, tools: [ { type: 'computer_20241022', @@ -130,9 +133,6 @@ const promptForAction = async ( }, }, ], - system: `The user will ask you to perform a task and you should use their computer to do so. After each step, take a screenshot and carefully evaluate if you have achieved the right outcome. Explicitly show your thinking: "I have evaluated step X..." If not correct, try again. Only when you confirm a step was executed correctly should you move on to the next one. Note that you have to click into the browser address bar before typing a URL. You should always call a tool! Always return a tool call. Remember call the finish_run tool when you have achieved the goal of the task. Do not explain you have finished the task, just call the tool. Use keyboard shortcuts to navigate whenever possible.`, - // tool_choice: { type: 'any' }, - messages: historyWithoutImages, betas: ['computer-use-2024-10-22'], }); @@ -218,7 +218,7 @@ export const runAgent = async ( } try { - const message = await promptForAction(getState().runHistory); + const message = await promptForAction(getState().runHistory, getState().systemPrompt); setState({ ...getState(), runHistory: [...getState().runHistory, message], diff --git a/src/main/store/types.ts b/src/main/store/types.ts index e05897a..306bb8d 100644 --- a/src/main/store/types.ts +++ b/src/main/store/types.ts @@ -19,12 +19,13 @@ export type AppState = { fullyAuto: boolean; running: boolean; error: string | null; - runHistory: BetaMessageParam[]; + systemPrompt: string; RUN_AGENT: () => void; STOP_RUN: () => void; SET_INSTRUCTIONS: (instructions: string) => void; SET_FULLY_AUTO: (fullyAuto: boolean) => void; + SET_SYSTEM_PROMPT: (systemPrompt: string) => void; CLEAR_HISTORY: () => void; }; diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 712f0e9..fb9ac22 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { Box, Button, @@ -8,6 +8,11 @@ import { Link, Switch, VStack, + Tabs, + TabList, + TabPanels, + Tab, + TabPanel, extendTheme, Spinner, useToast, @@ -18,6 +23,7 @@ import { Route, MemoryRouter as Router, Routes } from 'react-router-dom'; import { useDispatch } from 'zutron'; import { useStore } from './hooks/useStore'; import { RunHistory } from './RunHistory'; +import { SystemPrompt } from './SystemPrompt'; function Main() { const dispatch = useDispatch(window.zutron); @@ -28,11 +34,11 @@ function Main() { error, runHistory, } = useStore(); - // Add local state for instructions const [localInstructions, setLocalInstructions] = React.useState( savedInstructions ?? '', ); - const toast = useToast(); // Add toast hook + const toast = useToast(); + const [activeTab, setActiveTab] = useState(0); const startRun = () => { // Update Zustand state before starting the run @@ -59,7 +65,7 @@ function Main() { h="100vh" p={4} sx={{ - '-webkit-app-region': 'drag', // Make the background draggable + '-webkit-app-region': 'drag', }} > {/* Title heading no longer needs drag property since parent is draggable */} @@ -112,46 +118,66 @@ function Main() { pt={16} sx={{ '& > *': { - // Make all direct children non-draggable '-webkit-app-region': 'no-drag', }, }} > - ) => { - setLocalInstructions(e.target.value); - // Auto-adjust height - e.target.style.height = 'auto'; - e.target.style.height = `${e.target.scrollHeight}px`; - }} - onKeyDown={handleKeyDown} - /> + + + Main + System Prompt + + + + + + ) => { + setLocalInstructions(e.target.value); + e.target.style.height = 'auto'; + e.target.style.height = `${e.target.scrollHeight}px`; + }} + onKeyDown={handleKeyDown} + /> + {error && ( + + {error} + + )} + + + + + + + + + + + - - {/* Add error display */} - {error && ( - - {error} - - )} - - {/* RunHistory component */} - - - ); diff --git a/src/renderer/SystemPrompt.tsx b/src/renderer/SystemPrompt.tsx new file mode 100644 index 0000000..5fc98d8 --- /dev/null +++ b/src/renderer/SystemPrompt.tsx @@ -0,0 +1,47 @@ +import React, { useState } from 'react'; +import { + Box, + Button, + Textarea, + VStack, +} from '@chakra-ui/react'; +import { useDispatch } from 'zutron'; +import { useStore } from './hooks/useStore'; + +const DEFAULT_SYSTEM_PROMPT = `The user will ask you to perform a task and you should use their computer to do so. After each step, take a screenshot and carefully evaluate if you have achieved the right outcome. Explicitly show your thinking: "I have evaluated step X..." If not correct, try again. Only when you confirm a step was executed correctly should you move on to the next one. Note that you have to click into the browser address bar before typing a URL. You should always call a tool! Always return a tool call. Remember call the finish_run tool when you have achieved the goal of the task. Do not explain you have finished the task, just call the tool. Use keyboard shortcuts to navigate whenever possible.`; + +export function SystemPrompt() { + const dispatch = useDispatch(window.zutron); + const { systemPrompt } = useStore(); + const [localSystemPrompt, setLocalSystemPrompt] = useState(systemPrompt); + + const handleSave = () => { + dispatch({ type: 'SET_SYSTEM_PROMPT', payload: localSystemPrompt }); + }; + + const applyDefaultPrompt = () => { + setLocalSystemPrompt(DEFAULT_SYSTEM_PROMPT); + }; + + return ( + +