Files
BrowserOS/reference-code/old-lib/tools/bookmarks/common.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

236 lines
6.2 KiB
TypeScript

/**
* Common utilities and operations for bookmark tools
*/
/**
* Get the bookmark bar folder
*/
export async function getBookmarkBar(): Promise<chrome.bookmarks.BookmarkTreeNode | null> {
const tree = await chrome.bookmarks.getTree();
const root = tree[0];
for (const child of root.children || []) {
if (child.id === '1' || child.title === 'Bookmarks Bar') {
return child;
}
}
return null;
}
/**
* Find a folder by its path (e.g., "Work/Projects/React")
*/
export async function findFolderByPath(path: string): Promise<chrome.bookmarks.BookmarkTreeNode | null> {
const parts = path.split('/').filter(p => p.length > 0);
if (parts.length === 0) return null;
// Start from bookmark bar
const bookmarkBar = await getBookmarkBar();
if (!bookmarkBar) return null;
let currentFolder = bookmarkBar;
// Navigate through the path
for (const part of parts) {
const children = await chrome.bookmarks.getChildren(currentFolder.id);
const folder = children.find(child => !child.url && child.title === part);
if (!folder) {
return null; // Path not found
}
currentFolder = folder;
}
return currentFolder;
}
/**
* Get the full path of a folder from its ID
*/
export async function getFolderPath(folderId: string): Promise<string> {
const path: string[] = [];
let currentId = folderId;
while (currentId) {
try {
const folders = await chrome.bookmarks.get(currentId);
const folder = folders[0];
if (folder.title === 'Bookmarks Bar' || !folder.parentId) {
path.unshift('Bookmarks Bar');
break;
}
path.unshift(folder.title);
currentId = folder.parentId;
} catch {
break;
}
}
return path.join('/');
}
/**
* Find a child folder by name within a parent folder
*/
export async function findChildFolder(
parentId: string,
folderName: string
): Promise<chrome.bookmarks.BookmarkTreeNode | null> {
const children = await chrome.bookmarks.getChildren(parentId);
return children.find(child => !child.url && child.title === folderName) || null;
}
/**
* Check if a folder is a system folder
*/
export function isSystemFolder(folder: chrome.bookmarks.BookmarkTreeNode): boolean {
const systemFolders = ['Other Bookmarks', 'Mobile Bookmarks'];
return systemFolders.includes(folder.title);
}
/**
* Check if a folder is protected from deletion
*/
export function isProtectedFolder(folder: chrome.bookmarks.BookmarkTreeNode): boolean {
// Protect system folders by ID
const protectedIds = ['0', '1', '2']; // Root, Bookmarks Bar, Other Bookmarks
if (protectedIds.includes(folder.id)) {
return true;
}
// Protect by name
const protectedNames = [
'Bookmarks Bar',
'Other Bookmarks',
'Mobile Bookmarks',
'Sessions'
];
return protectedNames.includes(folder.title);
}
/**
* Recursively collect all bookmarks from a folder and its subfolders
*/
export async function collectAllBookmarksRecursively(
folderId: string,
parentTitle: string,
targetFolderToSkip?: string
): Promise<Array<{ id: string; title: string; url: string; parentTitle?: string }>> {
const allBookmarks: Array<{ id: string; title: string; url: string; parentTitle?: string }> = [];
try {
const children = await chrome.bookmarks.getChildren(folderId);
for (const child of children) {
if (child.url) {
// It's a bookmark - add it to the collection
allBookmarks.push({
id: child.id,
title: child.title,
url: child.url,
parentTitle: parentTitle
});
} else {
// It's a folder - skip target folder and recursively explore others
if (!targetFolderToSkip || child.title !== targetFolderToSkip) {
const childBookmarks = await collectAllBookmarksRecursively(
child.id,
child.title,
targetFolderToSkip
);
allBookmarks.push(...childBookmarks);
}
}
}
} catch (error) {
console.error(`Error collecting bookmarks from folder ${folderId}:`, error);
}
return allBookmarks;
}
/**
* Recursively clean up empty folders
*/
export async function cleanupEmptyFoldersRecursively(
parentFolderId: string,
targetFolderToProtect?: string
): Promise<void> {
try {
const children = await chrome.bookmarks.getChildren(parentFolderId);
const folders = children.filter(child => !child.url);
// Process folders in reverse order to handle nested cleanup properly
for (const folder of folders) {
// Skip protected folders
if ((targetFolderToProtect && folder.title === targetFolderToProtect) || isProtectedFolder(folder)) {
continue;
}
// First, recursively clean up subfolders
await cleanupEmptyFoldersRecursively(folder.id, targetFolderToProtect);
// After cleaning subfolders, check if this folder is now empty
const folderChildren = await chrome.bookmarks.getChildren(folder.id);
if (folderChildren.length === 0) {
await chrome.bookmarks.remove(folder.id);
}
}
} catch (error) {
console.error(`Error cleaning up folders in ${parentFolderId}:`, error);
}
}
/**
* Type for bookmark item with metadata
*/
export interface BookmarkWithMetadata {
id: string;
title: string;
url: string;
parentTitle?: string;
}
/**
* Type for folder statistics
*/
export interface FolderStats {
bookmarkCount: number;
subfolderCount: number;
totalItemCount: number;
}
/**
* Move all bookmarks from source folder to destination folder (non-recursive)
*/
export async function moveBookmarksToFolder(
sourceFolderId: string,
destinationFolderId: string
): Promise<number> {
let movedCount = 0;
try {
const children = await chrome.bookmarks.getChildren(sourceFolderId);
const bookmarks = children.filter(child => child.url);
for (const bookmark of bookmarks) {
try {
await chrome.bookmarks.move(bookmark.id, {
parentId: destinationFolderId
});
movedCount++;
} catch (error) {
console.error(`Failed to move bookmark ${bookmark.title}:`, error);
}
}
} catch (error) {
console.error(`Error moving bookmarks from ${sourceFolderId}:`, error);
}
return movedCount;
}