Files
BrowserOS/reference-code/old-lib/events/UIEventHandler.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

242 lines
6.5 KiB
TypeScript

import { StreamEventBus, StreamEvent } from './EventBus';
import { MessageType } from '@/lib/types/messaging';
/**
* Simplified UI message types that map to our stream events
*/
export enum UIMessageType {
SystemMessage = 'SystemMessage',
ThinkingMessage = 'ThinkingMessage',
NewSegment = 'NewSegment',
StreamingChunk = 'StreamingChunk',
FinalizeSegment = 'FinalizeSegment',
ToolCall = 'ToolCall',
ToolStream = 'ToolStream',
ToolResponse = 'ToolResponse',
DebugMessage = 'DebugMessage',
ErrorMessage = 'ErrorMessage',
CompleteMessage = 'CompleteMessage',
CancelMessage = 'CancelMessage'
}
/**
* UI message payload structure
*/
export interface UIMessage {
messageType: UIMessageType;
messageId?: string;
segmentId?: number;
content?: string;
toolName?: string;
toolArgs?: any;
toolResult?: string;
error?: string;
data?: any;
}
/**
* Handler that converts StreamEvents to UI messages
* This bridges the EventBus to the UI port messaging system
*/
export class UIEventHandler {
private eventBus: StreamEventBus;
private sendToUI: (type: MessageType, payload: any) => void;
private messageIdMap: Map<number, string> = new Map();
constructor(
eventBus: StreamEventBus,
sendToUI: (type: MessageType, payload: any) => void
) {
this.eventBus = eventBus;
this.sendToUI = sendToUI;
this.setupEventListeners();
}
/**
* Set up listeners for all event types
*/
private setupEventListeners(): void {
// Segment events
this.eventBus.onStreamEvent('segment.start', this.handleSegmentStart.bind(this));
this.eventBus.onStreamEvent('segment.chunk', this.handleSegmentChunk.bind(this));
this.eventBus.onStreamEvent('segment.end', this.handleSegmentEnd.bind(this));
// Tool events
this.eventBus.onStreamEvent('tool.start', this.handleToolStart.bind(this));
this.eventBus.onStreamEvent('tool.stream', this.handleToolStream.bind(this));
this.eventBus.onStreamEvent('tool.end', this.handleToolEnd.bind(this));
// System events
this.eventBus.onStreamEvent('system.message', this.handleSystemMessage.bind(this));
this.eventBus.onStreamEvent('system.thinking', this.handleSystemThinking.bind(this));
this.eventBus.onStreamEvent('system.error', this.handleSystemError.bind(this));
this.eventBus.onStreamEvent('system.complete', this.handleSystemComplete.bind(this));
this.eventBus.onStreamEvent('system.cancel', this.handleSystemCancel.bind(this));
// Debug events
this.eventBus.onStreamEvent('debug.message', this.handleDebugMessage.bind(this));
}
/**
* Send a UI message via port messaging
*/
private sendUIMessage(message: UIMessage): void {
this.sendToUI(MessageType.AGENT_STREAM_UPDATE, {
step: Date.now(), // Use timestamp as step for compatibility
action: message.messageType,
status: 'executing',
details: message
});
}
/**
* Event handlers
*/
private handleSegmentStart(event: StreamEvent): void {
const { segmentId, messageId } = event.data as any;
// Store message ID mapping
this.messageIdMap.set(segmentId, messageId);
this.sendUIMessage({
messageType: UIMessageType.NewSegment,
messageId,
segmentId
});
}
private handleSegmentChunk(event: StreamEvent): void {
const { segmentId, content, messageId } = event.data as any;
this.sendUIMessage({
messageType: UIMessageType.StreamingChunk,
messageId,
segmentId,
content
});
}
private handleSegmentEnd(event: StreamEvent): void {
const { segmentId, finalContent, messageId } = event.data as any;
this.sendUIMessage({
messageType: UIMessageType.FinalizeSegment,
messageId,
segmentId,
content: finalContent
});
}
private handleToolStart(event: StreamEvent): void {
const { toolName, displayName, icon, description, args } = event.data as any;
this.sendUIMessage({
messageType: UIMessageType.ToolCall,
toolName: displayName,
toolArgs: {
description,
icon,
args
}
});
}
private handleToolStream(event: StreamEvent): void {
const { toolName, content } = event.data as any;
this.sendUIMessage({
messageType: UIMessageType.ToolStream,
toolName,
content
});
}
private handleToolEnd(event: StreamEvent): void {
const { toolName, displayName, result } = event.data as any;
this.sendUIMessage({
messageType: UIMessageType.ToolResponse,
toolName: displayName,
toolResult: result,
content: result // For backward compatibility
});
}
private handleSystemMessage(event: StreamEvent): void {
const { message } = event.data as any;
this.sendUIMessage({
messageType: UIMessageType.SystemMessage,
content: message
});
}
private handleSystemError(event: StreamEvent): void {
const { error } = event.data as any;
this.sendUIMessage({
messageType: UIMessageType.ErrorMessage,
error,
content: error // For display
});
}
private handleSystemComplete(event: StreamEvent): void {
const { success, message } = event.data as any;
this.sendUIMessage({
messageType: UIMessageType.CompleteMessage,
content: message || (success ? '✅ Task completed successfully' : '❌ Task failed')
});
}
private handleSystemCancel(event: StreamEvent): void {
const { reason, userInitiated } = event.data as any;
if (userInitiated) {
this.sendUIMessage({
messageType: UIMessageType.CancelMessage,
content: reason || '✋ Task paused. To continue this task, just type your next request OR use 🔄 to start a new task!'
});
}
}
private handleSystemThinking(event: StreamEvent): void {
const { message, category } = event.data as any;
this.sendUIMessage({
messageType: UIMessageType.ThinkingMessage,
content: message,
data: { category }
});
}
private handleDebugMessage(event: StreamEvent): void {
const { message, data } = event.data as any;
this.sendUIMessage({
messageType: UIMessageType.DebugMessage,
content: message,
data
});
}
/**
* Clean up event listeners
*/
destroy(): void {
this.eventBus.removeAllListeners();
this.messageIdMap.clear();
}
/**
* Replay events for a late subscriber
*/
replay(): void {
this.eventBus.replay((event) => {
// Re-emit the event to trigger handlers
this.eventBus.emitStreamEvent(event);
});
}
}