Files
BrowserOS/reference-code/old-lib/prompts/BasePrompt.ts
Felarof 8245dfe0ff Rewrite Agent Loop (#7)
* clean-up bunch of files for re-write

* more clean-up and adding basic agent

* Minor fix moved types into respective files.

* Deleted bunch of old files

backup

Update gitignore

Deleted a bunch of files

Remove message manager

Deleted old docs

Update rules

rename Profiler to profiler

* Temporarily adding old code

* Adding two small things back

* backup

* Implemented LangChainProvider and updated cursor rules

backup

LangChainProvider

curosr rules

* Implement tests for LangChainProvider -- unit test and integration test

integration test passes

integration test backup

* Tool Design

Tools Desing

tools design

* NavigationTool ready

NavigationTool ready

NavigationTool ready

NaivgationTool ready

backup

* MessageManager

MessageManager

backup

* Fixed integration test

* Agent design new

Updated agent design and added bunch of /NTN commands

agent new design

* Delete old agent design

* MessageManagerReadOnly class

* PlannerTool ready

PlannerTool almost ready

* ToolManager and DoneTool

* Integration of BrowserAgent

* BrowserAgent implementation v0.1

* BrowserAgent small fix v0.2

* Tool calling design

too call design

tool design claude

* Update agent tool design with // NTN

* add zod-to-json npm install

* BrowserAGent v0.3

* BrowserAgent v0.4

* BrowserAgent v0.5

* fixes

* Build error fixes in my NEWLY added code

build errors fix

* Build error fixes in old code (integration work)

backup

* Comment StreamEventProcessor for now, it is not used

* Small build error fix

* Small rename

* Added integration test to check structuredLLM and changed to 4o-mini

change default to nxtscape

integration test

* Small docstring

* Simplified BrowserAgent code and added integration test

Simplified BrowserAgent code

BrowserAGent integrationt est

* Update CLAUDE.md with project memory and instructions on how to write code

Update CLAUDE.md with project memory and instructions on how to write code

Project Memory

* Just a mova.. Moved ToolManager outside. Build works.

* TabOperations tool

TabOperations Tool and fixing some test

tab operations

* Update CLAUDE.md

* Added ClassificationTool

classifiction tool

classification prommpt

* Refactored and simplified PlannerTool unit test and integration test

* Updated Plnnaer tool

* Update CLAUDE.md

* BrowserAgent modified to do classification

BrowserAgent with classification

* minor fix to ToolManager

* Instead of ToolCall and ToolResult -- just updating message manager once

* minor fix to BrowserAgent integration test

* Changed done to "done_tool"

* Updated CLAUDE.md to reflect understanding of claude

* Uncommented stream event processor

* Renamed EventBus to StreamEventBus

* Commented StreamEventProcessor

* Event Processor

* Integrated EventProcessor with BrowserAgent

Added EventProcessor to BrowserAgetn

* Renamed StreamEventBus to EventBus

* Made EventBus required parameter in ExecutionContext

* PlanGenerator rewrite

PlanGenerator rewrite

backup

* For simple task, explicitly tell it to call done tool

* Max attempts for simple task

* backup

* Revert "backup"

This reverts commit 7d79a3d4d5774bfef79ec9827878b74edad3593f.

* Consolidating where EventBus and EventProcessor are created and initialized

backup

* Update CLAUDE.md

Update CLAUDE.md

* Improving agent loop code

Cleaned up processTooCall

classification task

* Create test-writer subAgent

test-agent-prompt

test agent prompt

test-agent-prompt

Update test-writer.md

* BrowserAgent test

Browseragent test

BrowserAgent test

* BrowserAgent refactor

backup

backup

* Minor fixes

* Minor fix

* minor change -- NEW AGENT LOOP IS WORKING WELL

* Update cursor rules

* Small change

* Improved BrowserAgent integration test

Improved BrowserAgent integration test

* Small change

* Update CLAUDE.md

* Different tools

* FindElementTool is ready

Find element update

backup

find element backup

* Updated to test strings to say "tests..."

* ScrollTool is ready

* RefreshStateTool is updated as well

* MessageManager updated

* SearchTool is ready

backup

* Interaction Element is also ready

* Add debugMessage emitter

* ValidatorTool ready and tests are passing

Validation Tool

validator tool

backup

backup

* GroupTabs tool ready

* Registered all the tools

* Planning changed to 5 steps

* BrowserAgent integration test fix

* Minor string changes

* backup

* Removed too many confusing events in EventProcessor -- there is only event.info right now

* Abort control implemented

backup

Abort

* Formatter for toolResult

Formatter for toolResult

backup

* Always render using Markdown

* Minor fix

---------

Co-authored-by: Nikhil Sonti <nikhilsv92@gmail.com>
2025-07-29 08:14:45 -07:00

186 lines
6.0 KiB
TypeScript

import { z } from 'zod';
import { HumanMessage } from '@langchain/core/messages';
import { wrapUntrustedContent } from '@/lib/utils/MessageUtils';
import { ExecutionContext } from '@/lib/runtime/ExecutionContext';
/**
* Base abstract class for all agent prompts.
* Provides a structured way to build and manage complex prompts.
*/
export abstract class BasePrompt {
/**
* The name of the agent this prompt is for
*/
protected abstract readonly agentName: string;
/**
* Tool documentation string (if any)
*/
protected toolDocumentation: string = '';
/**
* Constructor
* @param toolDocumentation - Optional tool documentation to include
*/
constructor(toolDocumentation?: string) {
if (toolDocumentation) {
this.toolDocumentation = toolDocumentation;
}
}
/**
* Generate the complete prompt by combining all sections
* @returns The complete system prompt
*/
public abstract generate(): string;
/**
* Builds the user message containing the browser state
* @param context - The agent context containing browser state and options
* @param useVision - Legacy parameter, ignored in V2 (no vision support)
* @returns HumanMessage with browser state information
*/
public async buildBrowserStateUserMessage(context: ExecutionContext, useVision: boolean): Promise<HumanMessage> {
// Get browser state (V2 doesn't support vision/screenshots)
const browserState = await context.browserContext.getBrowserState();
// Get interactive elements as pre-formatted string
// V2 provides both clickable and typeable elements
// Note: The numbers in brackets [11], [23] etc. are nodeIds which are sequential indices
const clickableElements = browserState.clickableElementsString;
const typeableElements = browserState.typeableElementsString;
// Combine elements into a single display
let rawElementsText = '';
if (clickableElements || typeableElements) {
const parts: string[] = [];
if (clickableElements) {
parts.push('Clickable elements (use the nodeId in brackets with tools):\n' + clickableElements);
}
if (typeableElements) {
parts.push('Input fields (use the nodeId in brackets with tools):\n' + typeableElements);
}
rawElementsText = parts.join('\n\n');
}
// V2 doesn't provide scroll position info, so we simplify the format
let formattedElementsText = '';
if (rawElementsText !== '') {
// Wrap untrusted content for security
const elementsText = wrapUntrustedContent(rawElementsText);
formattedElementsText = `[Page content]\n${elementsText}\n[End of visible content]`;
} else {
formattedElementsText = 'empty page';
}
// Add current date/time
const timeStr = new Date().toISOString().slice(0, 16).replace('T', ' '); // Format: YYYY-MM-DD HH:mm
const stepInfoDescription = `\nCurrent date and time: ${timeStr}`;
// Format current tab info
const currentTab = `{id: ${browserState.tabId}, url: ${browserState.url}, title: ${browserState.title}}`;
// Format other tabs
const otherTabs = browserState.tabs
.filter((tab: any) => tab.id !== browserState.tabId)
.map((tab: any) => `- {id: ${tab.id}, url: ${tab.url}, title: ${tab.title}}`);
// Build complete state description
const stateDescription = `
[Task history memory ends]
[Current state starts here]
The following is one-time information - if you need to remember it write it to memory:
Current tab: ${currentTab}
Other available tabs:
${otherTabs.join('\n ')}
Interactive elements from the current page (numbers in [brackets] are nodeIds to use with interact/find_element tools):
${formattedElementsText}
${stepInfoDescription}
`;
// V2 doesn't support screenshots, always return text-only message
// TODO: add screenshot if available
return new HumanMessage(stateDescription);
}
/**
* Helper method to join sections with proper spacing
* @param sections - Array of prompt sections
* @returns Joined prompt string
*/
protected joinSections(...sections: string[]): string {
return sections
.filter(section => section.trim().length > 0)
.join('\n\n');
}
/**
* Format a section with a header
* @param header - Section header
* @param content - Section content
* @returns Formatted section
*/
protected formatSection(header: string, content: string): string {
return `## ${header}\n${content}`;
}
/**
* Format a subsection with a header
* @param header - Subsection header
* @param content - Subsection content
* @returns Formatted subsection
*/
protected formatSubsection(header: string, content: string): string {
return `### ${header}:\n${content}`;
}
/**
* Create a bullet list from items
* @param items - Array of items
* @param indent - Indentation level (0 = -, 1 = •, 2 = ◦)
* @returns Formatted bullet list
*/
protected bulletList(items: string[], indent: number = 0): string {
const bullets = ['-', '•', '◦'];
const bullet = bullets[Math.min(indent, bullets.length - 1)];
const indentStr = ' '.repeat(indent);
return items
.map(item => `${indentStr}${bullet} ${item}`)
.join('\n');
}
/**
* Create a numbered list from items
* @param items - Array of items
* @param startNumber - Starting number
* @returns Formatted numbered list
*/
protected numberedList(items: string[], startNumber: number = 1): string {
return items
.map((item, index) => `${startNumber + index}. ${item}`)
.join('\n');
}
/**
* Format code block
* @param code - Code content
* @param language - Language identifier
* @returns Formatted code block
*/
protected codeBlock(code: string, language: string = ''): string {
return `\`\`\`${language}\n${code}\n\`\`\``;
}
/**
* Create a divider line
* @param char - Character to use for divider
* @param length - Length of divider
* @returns Divider string
*/
protected divider(char: string = '─', length: number = 40): string {
return char.repeat(length);
}
}