Skip to content

Commit 5816ee8

Browse files
authored
Merge pull request #164 from Cloud-Code-AI/122-actions-for-agent---click-copy-select-check
122 actions for agent click copy select check
2 parents c9471ae + c490deb commit 5816ee8

File tree

10 files changed

+2424
-80
lines changed

10 files changed

+2424
-80
lines changed

extensions/chrome/public/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959

6060
"web_accessible_resources": [
6161
{
62-
"resources": ["src/core/browser-actions.js"],
62+
"resources": ["src/core/browser-actions.js", "src/core/agent/html-cleaner.js"],
6363
"matches": ["<all_urls>"]
6464
}
6565
]
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import { useState, useEffect } from 'react';
2+
import { HTMLCleaner } from '@browserai/browserai';
3+
import { Button } from './ui/button';
4+
import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs';
5+
import { Textarea } from './ui/textarea';
6+
7+
export function HTMLCleanerTest() {
8+
const [originalHtml, setOriginalHtml] = useState<string>('');
9+
const [cleanedHtml, setCleanedHtml] = useState<string>('');
10+
const [loading, setLoading] = useState<boolean>(false);
11+
const [error, setError] = useState<string | null>(null);
12+
13+
// Get the HTML of the current page
14+
const getCurrentPageHtml = async () => {
15+
setLoading(true);
16+
setError(null);
17+
18+
try {
19+
// Query the active tab
20+
const tabs = await chrome.tabs.query({ active: true, currentWindow: true });
21+
if (!tabs[0]?.id) {
22+
throw new Error('No active tab found');
23+
}
24+
25+
// Execute script to get the HTML
26+
const results = await chrome.scripting.executeScript({
27+
target: { tabId: tabs[0].id },
28+
func: () => document.documentElement.outerHTML
29+
});
30+
31+
const html = results[0]?.result as string;
32+
setOriginalHtml(html);
33+
} catch (err) {
34+
setError(`Error getting page HTML: ${err instanceof Error ? err.message : String(err)}`);
35+
} finally {
36+
setLoading(false);
37+
}
38+
};
39+
40+
// Clean the HTML
41+
const cleanHtml = () => {
42+
try {
43+
const htmlCleaner = new HTMLCleaner();
44+
45+
// Use the new cleanWithElementIDs method
46+
const { content, elements, references } = htmlCleaner.cleanWithElementIDs(originalHtml);
47+
// const formattedResult = htmlCleaner.cleanSemantic(originalHtml)
48+
49+
// Format the result to display content and element references
50+
const formattedResult = content;
51+
// const formattedResult = `
52+
// # Cleaned Content
53+
// ${content}
54+
55+
// # Element References
56+
// ${Object.entries(elements).map(([id, info]) =>
57+
// `- [${id}]: ${info.type} "${info.text}"${
58+
// info.attributes ? ` (${Object.entries(info.attributes)
59+
// .map(([k, v]) => `${k}="${v}"`)
60+
// .join(', ')})` : ''
61+
// }`
62+
// ).join('\n')}
63+
64+
// # Link References
65+
// ${Object.entries(references)
66+
// .filter(([_, url]) => url)
67+
// .map(([id, url]) => `- [${id}]: ${url}`)
68+
// .join('\n')}
69+
// `;
70+
console.log(elements, references)
71+
setCleanedHtml(formattedResult);
72+
} catch (err) {
73+
setError(`Error cleaning HTML: ${err instanceof Error ? err.message : String(err)}`);
74+
}
75+
};
76+
77+
// Effect to get the HTML when the component mounts
78+
useEffect(() => {
79+
getCurrentPageHtml();
80+
}, []);
81+
82+
return (
83+
<div className="p-4 flex flex-col gap-4">
84+
<div className="flex justify-between items-center">
85+
<h2 className="text-lg font-semibold">HTML Cleaner Test</h2>
86+
<div className="flex gap-2">
87+
<Button
88+
variant="outline"
89+
size="sm"
90+
onClick={getCurrentPageHtml}
91+
disabled={loading}
92+
>
93+
Refresh HTML
94+
</Button>
95+
<Button
96+
variant="default"
97+
size="sm"
98+
onClick={cleanHtml}
99+
disabled={loading || !originalHtml}
100+
>
101+
Clean HTML
102+
</Button>
103+
</div>
104+
</div>
105+
106+
{error && (
107+
<div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
108+
{error}
109+
</div>
110+
)}
111+
112+
<Tabs defaultValue="original">
113+
<TabsList className="grid w-full grid-cols-2">
114+
<TabsTrigger value="original">Original HTML</TabsTrigger>
115+
<TabsTrigger value="cleaned">Cleaned HTML</TabsTrigger>
116+
</TabsList>
117+
<TabsContent value="original" className="mt-2">
118+
<Textarea
119+
value={originalHtml}
120+
onChange={(e) => setOriginalHtml(e.target.value)}
121+
className="h-[400px] font-mono text-xs"
122+
placeholder={loading ? "Loading HTML..." : "No HTML content"}
123+
/>
124+
</TabsContent>
125+
<TabsContent value="cleaned" className="mt-2">
126+
<Textarea
127+
value={cleanedHtml}
128+
readOnly
129+
className="h-[400px] font-mono text-xs"
130+
placeholder="Cleaned HTML will appear here"
131+
/>
132+
{cleanedHtml && (
133+
<div className="text-xs text-gray-500 mt-1">
134+
Total length: {cleanedHtml.length} characters
135+
</div>
136+
)}
137+
</TabsContent>
138+
</Tabs>
139+
</div>
140+
);
141+
}

extensions/chrome/src/components/ui/textarea.tsx

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,23 @@ import * as React from "react"
22

33
import { cn } from "../../lib/utils"
44

5-
const Textarea = React.forwardRef<
6-
HTMLTextAreaElement,
7-
React.ComponentProps<"textarea">
8-
>(({ className, ...props }, ref) => {
9-
return (
10-
<textarea
11-
className={cn(
12-
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
13-
className
14-
)}
15-
ref={ref}
16-
{...props}
17-
/>
18-
)
19-
})
5+
export interface TextareaProps
6+
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
7+
8+
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
9+
({ className, ...props }, ref) => {
10+
return (
11+
<textarea
12+
className={cn(
13+
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
14+
className
15+
)}
16+
ref={ref}
17+
{...props}
18+
/>
19+
)
20+
}
21+
)
2022
Textarea.displayName = "Textarea"
2123

2224
export { Textarea }

extensions/chrome/src/popup/navigation.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// import { MessageSquare, Workflow, ArrowUpCircle, Play } from "lucide-react"
2-
import { MessageSquare, Workflow, ArrowUpCircle } from "lucide-react"
2+
import { MessageSquare, Workflow, ArrowUpCircle, Play, Code } from "lucide-react"
33
import { useState, useEffect } from 'react'
44

55
export function Navigation() {
@@ -29,7 +29,7 @@ export function Navigation() {
2929
<MessageSquare className="h-5 w-5 mb-1" />
3030
<span>Chat</span>
3131
</button>
32-
{/* <button
32+
<button
3333
className={`nav-button flex flex-col items-center w-24 ${currentView === 'runner-view' ? 'active' : ''}`}
3434
onClick={() => window.location.hash = '#runner-view'}
3535
>
@@ -40,9 +40,17 @@ export function Navigation() {
4040
className={`nav-button flex flex-col items-center w-24 ${currentView === 'content-identifier-test' ? 'active' : ''}`}
4141
onClick={() => window.location.hash = '#content-identifier-test'}
4242
>
43-
<Play className="h-5 w-5 mb-1" />
44-
<span>Test</span>
45-
</button> */}
43+
<Code className="h-5 w-5 mb-1" />
44+
<span>Content Identifier Test</span>
45+
</button>
46+
<button
47+
className={`nav-button flex flex-col items-center w-24 ${currentView === 'html-cleaner-test' ? 'active' : ''}`}
48+
onClick={() => window.location.hash = '#html-cleaner-test'}
49+
>
50+
<Code className="h-5 w-5 mb-1" />
51+
<span>HTML Test</span>
52+
</button>
53+
4654
<button
4755
className={`nav-button flex flex-col items-center w-24`}
4856
onClick={() => window.open('https://browseragent.dev/pricing/', '_blank')}

extensions/chrome/src/popup/popup.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { createRoot } from 'react-dom/client'
88
import { ChatInterface } from "./chat-interface"
99
import { WorkflowRunner } from "../sidepanel/workflow-runner"
1010
import { ContentIdentifierTest } from "../sidepanel/content-identifier-test"
11+
import { HTMLCleanerTest } from "../components/HTMLCleanerTest"
1112

1213
interface Workflow {
1314
id: string
@@ -52,6 +53,8 @@ export default function Popup() {
5253
return <WorkflowRunner />
5354
case 'content-identifier-test':
5455
return <ContentIdentifierTest />
56+
case 'html-cleaner-test':
57+
return <HTMLCleanerTest />
5558
case 'workflow-view':
5659
default:
5760
return (

extensions/chrome/src/sidepanel.tsx

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,46 @@
1-
import React from 'react'
1+
import React, { useState } from 'react'
22
import ReactDOM from 'react-dom/client'
33
import './App.css'
44
import './index.css'
5-
import App from './App'
5+
import { Button } from './components/ui/button'
6+
import { HTMLCleanerTest } from './components/HTMLCleanerTest'
67

78
function SidePanel() {
9+
const [currentView, setCurrentView] = useState<'main' | 'htmlCleaner'>('main')
10+
811
return (
9-
<div className="sidepanel-container" style={{
10-
width: '100%',
11-
height: '100vh',
12-
padding: '16px',
13-
backgroundColor: '#ffffff',
14-
color: '#213547'
15-
}}>
16-
<h2>Browser AI Side Panel</h2>
17-
<App />
12+
<div className="flex flex-col h-screen">
13+
<header className="border-b p-4">
14+
<h1 className="text-lg font-bold">Browser AI</h1>
15+
</header>
16+
17+
<nav className="border-b p-2 flex gap-2">
18+
<Button
19+
variant={currentView === 'main' ? 'default' : 'outline'}
20+
size="sm"
21+
onClick={() => setCurrentView('main')}
22+
>
23+
Main
24+
</Button>
25+
<Button
26+
variant={currentView === 'htmlCleaner' ? 'default' : 'outline'}
27+
size="sm"
28+
onClick={() => setCurrentView('htmlCleaner')}
29+
>
30+
HTML Cleaner
31+
</Button>
32+
</nav>
33+
34+
<main className="flex-1 overflow-auto">
35+
{currentView === 'main' && (
36+
<div className="p-4">
37+
<h2 className="text-lg font-semibold mb-4">Browser AI</h2>
38+
<p>Use this panel to interact with your AI assistant.</p>
39+
</div>
40+
)}
41+
42+
{currentView === 'htmlCleaner' && <HTMLCleanerTest />}
43+
</main>
1844
</div>
1945
)
2046
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@browserai/browserai",
3-
"version": "1.0.31",
3+
"version": "1.0.35",
44
"private": false,
55
"description": "A library for running AI models directly in the browser",
66
"main": "dist/index.js",

0 commit comments

Comments
 (0)