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

178 lines
4.9 KiB
TypeScript

import { z } from 'zod';
import { NxtscapeTool } from '../base/NxtscapeTool';
import { ToolConfig } from '../base/ToolConfig';
import { ExecutionContext } from '@/lib/runtime/ExecutionContext';
import { getFolderPath } from './common';
/**
* Input schema for save bookmark tool
*/
export const SaveBookmarkInputSchema = z.object({
folder_id: z.string(), // Required - where to save
tab_id: z.number().optional() // Optional - defaults to current tab
});
export type SaveBookmarkInput = z.infer<typeof SaveBookmarkInputSchema>;
/**
* Output schema for save bookmark tool
*/
export const SaveBookmarkOutputSchema = z.object({
success: z.boolean(),
message: z.string()
});
export type SaveBookmarkOutput = z.infer<typeof SaveBookmarkOutputSchema>;
/**
* Tool for saving tabs as bookmarks - simple and focused
*/
export class SaveBookmarkTool extends NxtscapeTool<SaveBookmarkInput, SaveBookmarkOutput> {
constructor(executionContext: ExecutionContext) {
const config: ToolConfig<SaveBookmarkInput, SaveBookmarkOutput> = {
name: 'save_bookmark',
description: 'Save a browser tab as a bookmark. Saves current tab by default, or specify tab_id for a specific tab. Always requires folder_id.',
category: 'bookmarks',
version: '1.0.0',
inputSchema: SaveBookmarkInputSchema,
outputSchema: SaveBookmarkOutputSchema,
examples: [
{
description: 'Save current tab to a folder',
input: {
folder_id: 'folder_123'
},
output: {
success: true,
message: 'Successfully saved "React Documentation" to Bookmarks Bar/Development'
}
},
{
description: 'Save specific tab to a folder',
input: {
folder_id: 'folder_456',
tab_id: 5
},
output: {
success: true,
message: 'Successfully saved "TypeScript Guide" to Bookmarks Bar/Learning'
}
}
],
streamingConfig: {
displayName: 'Save Bookmark',
icon: '🔖',
progressMessage: 'Saving bookmark...'
}
};
super(config, executionContext);
}
/**
* Override: Generate contextual display message
*/
getProgressMessage(args: SaveBookmarkInput): string {
try {
// Note: args should already be parsed by StreamEventProcessor
if (args?.tab_id) {
return `Saving tab ${args.tab_id} as bookmark...`;
}
return 'Saving current tab as bookmark...';
} catch {
return 'Saving bookmark...';
}
}
/**
* Override: Format result for display
*/
FormatResultForUI(output: SaveBookmarkOutput): string {
if (output.success) {
return `${output.message}`;
}
return `${output.message}`;
}
protected async execute(input: SaveBookmarkInput): Promise<SaveBookmarkOutput> {
const { folder_id, tab_id } = input;
try {
// Verify the folder exists and is valid
let folderPath: string;
try {
const folders = await chrome.bookmarks.get(folder_id);
const folder = folders[0];
if (folder.url) {
return {
success: false,
message: 'Specified ID is not a folder'
};
}
folderPath = await getFolderPath(folder_id);
} catch {
return {
success: false,
message: 'Folder not found'
};
}
// Get the tab to save
let tabToSave: chrome.tabs.Tab | null = null;
if (tab_id !== undefined) {
// Get specific tab by ID
try {
tabToSave = await chrome.tabs.get(tab_id);
if (!tabToSave.url || !tabToSave.title) {
return {
success: false,
message: `Tab ${tab_id} is not a valid tab to bookmark`
};
}
} catch {
return {
success: false,
message: `Tab ${tab_id} not found`
};
}
} else {
// Get current active tab
const tabs = await chrome.tabs.query({ active: true, currentWindow: true });
if (tabs.length === 0) {
return {
success: false,
message: 'No active tab found'
};
}
tabToSave = tabs[0];
if (!tabToSave.url || !tabToSave.title) {
return {
success: false,
message: 'Current tab cannot be bookmarked'
};
}
}
// Create the bookmark
const bookmark = await chrome.bookmarks.create({
parentId: folder_id,
title: tabToSave.title,
url: tabToSave.url
});
return {
success: true,
message: `Successfully saved "${tabToSave.title}" to ${folderPath}`
};
} catch (error) {
console.error('[save_bookmark] Error:', error);
return {
success: false,
message: `Failed to save bookmark: ${error instanceof Error ? error.message : String(error)}`
};
}
}
}