browser-use-typescript
Version:
A TypeScript-based browser automation framework
166 lines (160 loc) • 6.35 kB
JavaScript
import { SystemMessage, HumanMessage } from "@langchain/core/messages";
import { system_prompt } from "./system_prompt";
/**
* Defines the system prompt for the browser automation agent
*/
export class SystemPrompt {
defaultActionDescription;
maxActionsPerStep;
promptTemplate = '';
systemMessage;
constructor(actionDescription, maxActionsPerStep = 10, overrideSystemMessage, extendSystemMessage) {
this.defaultActionDescription = actionDescription;
this.maxActionsPerStep = maxActionsPerStep;
let prompt = '';
if (overrideSystemMessage) {
prompt = overrideSystemMessage;
}
else {
this.loadPromptTemplate();
prompt = this.promptTemplate.replace('{max_actions}', this.maxActionsPerStep.toString());
}
if (extendSystemMessage) {
prompt += `\n${extendSystemMessage}`;
}
this.systemMessage = new SystemMessage(prompt);
}
/**
* Load the prompt template from the markdown file
*/
loadPromptTemplate() {
try {
// For browser environment, we'll need to handle this differently
// In Next.js, you might want to import this as a static file
this.promptTemplate = system_prompt;
}
catch (e) {
console.error('Failed to load system prompt template:', e);
// Fallback to basic prompt if file can't be loaded
this.promptTemplate = `You are a browser automation agent. You can perform up to {max_actions} actions per step.`;
}
}
/**
* Get the system message for the agent
*/
getSystemMessage() {
return this.systemMessage;
}
}
/**
* Interface for agent step information
/**
* Formats messages for the agent from browser state
*/
export class AgentMessagePrompt {
state;
result;
includeAttributes;
stepInfo;
constructor(state, result, includeAttributes = [], stepInfo) {
this.state = state;
this.result = result;
this.includeAttributes = includeAttributes;
this.stepInfo = stepInfo;
}
/**
* Get a formatted user message containing browser state
*/
getUserMessage(useVision = true) {
const elementsText = this.state.elementTree?.clickableElementsToString(this.includeAttributes) || '';
const hasContentAbove = (this.state.pixels_above || 0) > 0;
const hasContentBelow = (this.state.pixels_below || 0) > 0;
let formattedElementsText = '';
if (elementsText !== '') {
if (hasContentAbove) {
formattedElementsText =
`... ${this.state.pixels_above} pixels above - scroll or extract content to see more ...\n${elementsText}`;
}
else {
formattedElementsText = `[Start of page]\n${elementsText}`;
}
if (hasContentBelow) {
formattedElementsText =
`${formattedElementsText}\n... ${this.state.pixels_below} pixels below - scroll or extract content to see more ...`;
}
else {
formattedElementsText = `${formattedElementsText}\n[End of page]`;
}
}
else {
formattedElementsText = 'empty page';
}
let stepInfoDescription = '';
if (this.stepInfo) {
stepInfoDescription = `Current step: ${this.stepInfo.step_number + 1}/${this.stepInfo.max_steps}`;
}
const timeStr = new Date().toLocaleString();
stepInfoDescription += `\nCurrent date and time: ${timeStr}`;
let 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 url: ${this.state.url || ''}
Available tabs:
${this.state.tab || ''}
Interactive elements from top layer of the current page inside the viewport:
${formattedElementsText}
${stepInfoDescription}
`;
if (this.result && this.result.length > 0) {
this.result.forEach((result, i) => {
if (result.extractedContent) {
stateDescription += `\nAction result ${i + 1}/${this.result.length}: ${result.extractedContent}`;
}
if (result.error) {
// Only use last line of error
const error = result.error.split('\n').pop() || '';
stateDescription += `\nAction error ${i + 1}/${this.result.length}: ...${error}`;
}
});
}
if (this.state.screenshot && useVision) {
// Format message for vision model
return new HumanMessage({
content: [
{ type: 'text', text: stateDescription },
{
type: 'image_url',
image_url: { url: `data:image/png;base64,${this.state.screenshot}` }
}
]
});
}
return new HumanMessage(stateDescription);
}
}
/**
* Specialized system prompt for planning agent
*/
export class PlannerPrompt extends SystemPrompt {
getSystemMessage() {
return new SystemMessage(`You are a planning agent that helps break down tasks into smaller steps and reason about the current state.
Your role is to:
1. Analyze the current state and history
2. Evaluate progress towards the ultimate goal
3. Identify potential challenges or roadblocks
4. Suggest the next high-level steps to take
Inside your messages, there will be AI messages from different agents with different formats.
Your output format should be always a JSON object with the following fields:
{
"state_analysis": "Brief analysis of the current state and what has been done so far",
"progress_evaluation": "Evaluation of progress towards the ultimate goal (as percentage and description)",
"challenges": "List any potential challenges or roadblocks",
"next_steps": "List 2-3 concrete next steps to take",
"reasoning": "Explain your reasoning for the suggested next steps"
}
Ignore the other AI messages output structures.
Keep your responses concise and focused on actionable insights.`);
}
}
//# sourceMappingURL=prompt.js.map