Skip to content

Commit 64c9bce

Browse files
committed
Added a better web browser for OS control
Uses a text fetch instead of screenshots like other agentic OS control browsers.
1 parent 647c628 commit 64c9bce

4 files changed

Lines changed: 171 additions & 7 deletions

File tree

Project_Andrew/agent_designer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#V03172026
1+
#V03232026
22
# =============================================================================
33
# Chaos AI-OS — Agent Designer Plugin (KB-Integrated)
44
# Now logs discoveries and checks knowledge base before creating specialists
@@ -88,7 +88,7 @@ def design_agent(
8888
context = {
8989
'agent_goal': goal, # This contains the Sovereign Axioms if tier=0
9090
'traits': traits or {'intelligence': 0.9, 'honesty': 1.0, 'caution': 0.8},
91-
'tools': tools or ['web_search', 'code_execution', 'memory', 'cpol'],
91+
'tools': tools or ['web_search', 'semantic_fetch', 'code_execution', 'memory', 'cpol'],
9292
'safety_multiplier': safety_multiplier,
9393
'self_healing': True,
9494
'cpol_mode': 'full',

Project_Andrew/caios_browser.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#V03232026
2+
def fetch_structured(url: str) -> Dict:
3+
"""
4+
Agent-optimized page fetcher.
5+
Returns semantic structure not visual layout.
6+
No screenshots. No coordinates. No tooltips.
7+
"""
8+
raw = requests.get(url, headers=agent_headers)
9+
10+
return {
11+
'title': extract_title(raw),
12+
'main_content': extract_body(raw),
13+
'links': extract_links(raw),
14+
'forms': extract_forms(raw),
15+
'metadata': extract_meta(raw),
16+
'structured_data': extract_json_ld(raw)
17+
}

Project_Andrew/orchestrator.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#V03182026
1+
#V03232026
22
# =============================================================================
33
# Chaos AI-OS – Hardened Orchestrator (Unified Edition)
44
# Combines: V1 Logic + V3 Pipeline + Mesh Encryption + Chatbot Safety
@@ -104,7 +104,12 @@
104104
'last_assistant_message': '',
105105
'swarm_leaders': [], # Mesh networking
106106
'active_syncs': {}, # Deduplication cache
107-
'api_clients': {} # Multi-model swarm clients
107+
'api_clients': {}, # Multi-model swarm clients
108+
'available_tools': [ # Agent-accessible tool registry
109+
'web_search',
110+
'semantic_fetch', # CPOL-gated semantic web fetcher
111+
'memory'
112+
]
108113
}
109114

110115
class UnifiedAbstractionManager:

Project_Andrew/os_control.py

Lines changed: 145 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#V03172026
1+
#V03232026
22
# =============================================================================
33
# Chaos AI-OS — OS Control Layer
44
# CPOL-gated system operations with Asimov compliance
@@ -21,6 +21,7 @@
2121
'network_request': 0.6, # Medium - depends on destination
2222
'file_write': 0.4, # Low-medium - new file creation
2323
'file_read': 0.1, # Low - read only, no state change
24+
'semantic_fetch': 0.2, # Read-only web, low risk
2425
}
2526

2627
class OSController:
@@ -140,6 +141,74 @@ def read_file(self, path: str) -> Dict[str, Any]:
140141
except Exception as e:
141142
return {'status': 'error', 'error': str(e)}
142143

144+
def fetch_url(self, url: str,
145+
extract_mode: str = 'content') -> Dict[str, Any]:
146+
"""
147+
Agent-optimized semantic web fetcher.
148+
Strips visual noise, tooltips, scripts, ads.
149+
Returns structured content safe for agent consumption.
150+
No screenshots. No coordinates. No focus hijacking.
151+
152+
extract_mode: 'content' | 'links' | 'forms' | 'full'
153+
"""
154+
gate = self._gate_action('semantic_fetch', url)
155+
156+
if gate['decision'] == 'block':
157+
self._log_action('semantic_fetch', url, 'blocked')
158+
return {'status': 'blocked', 'reason': gate['reason']}
159+
160+
try:
161+
import urllib.request
162+
import html.parser
163+
164+
# Security: validate URL before fetch
165+
if not url.startswith(('http://', 'https://')):
166+
return {'status': 'blocked',
167+
'reason': 'Invalid URL scheme'}
168+
169+
# Simple embedded code attack mitigation
170+
BLOCKED_PATTERNS = [
171+
'javascript:', 'data:', 'vbscript:',
172+
'onload=', 'onerror=', 'onclick='
173+
]
174+
175+
headers = {
176+
'User-Agent': 'CAIOS-Agent/1.0 (semantic fetch)',
177+
'Accept': 'text/html,application/xhtml+xml',
178+
}
179+
180+
req = urllib.request.Request(url, headers=headers)
181+
with urllib.request.urlopen(req, timeout=10) as response:
182+
raw_html = response.read().decode('utf-8', errors='ignore')
183+
184+
# Check for embedded attack patterns
185+
raw_lower = raw_html.lower()
186+
detected_threats = [p for p in BLOCKED_PATTERNS
187+
if p in raw_lower]
188+
if len(detected_threats) > 2:
189+
self._log_action('semantic_fetch', url,
190+
'blocked_malicious_content')
191+
return {
192+
'status': 'blocked',
193+
'reason': f'Potential malicious content: '
194+
f'{detected_threats}'
195+
}
196+
197+
# Strip to semantic content
198+
result = self._extract_semantic(raw_html, extract_mode)
199+
self._log_action('semantic_fetch', url, 'allowed')
200+
201+
return {
202+
'status': 'success',
203+
'url': url,
204+
'extract_mode': extract_mode,
205+
'content': result
206+
}
207+
208+
except Exception as e:
209+
self._log_action('semantic_fetch', url, f'error: {e}')
210+
return {'status': 'error', 'error': str(e)}
211+
143212
def write_file(self, path: str, content: str,
144213
overwrite: bool = False) -> Dict[str, Any]:
145214
"""Write file - medium risk if overwrite."""
@@ -212,6 +281,71 @@ def execute_script(self, script: str,
212281
return {'status': 'error', 'error': str(e)}
213282

214283

284+
def _extract_semantic(self, html: str,
285+
mode: str = 'content') -> Dict:
286+
"""
287+
Strip visual noise. Return semantic structure only.
288+
No JS. No CSS. No tooltips. No ads. No tracking.
289+
Pure content for agent consumption.
290+
"""
291+
import re
292+
293+
# Remove script tags and contents
294+
html = re.sub(r'<script[^>]*>.*?</script>',
295+
'', html, flags=re.DOTALL | re.IGNORECASE)
296+
# Remove style tags
297+
html = re.sub(r'<style[^>]*>.*?</style>',
298+
'', html, flags=re.DOTALL | re.IGNORECASE)
299+
# Remove comments
300+
html = re.sub(r'<!--.*?-->', '', html, flags=re.DOTALL)
301+
# Remove event handlers
302+
html = re.sub(r'\s+on\w+="[^"]*"', '', html)
303+
html = re.sub(r"\s+on\w+='[^']*'", '', html)
304+
305+
# Extract by mode
306+
if mode == 'content':
307+
# Get text content only
308+
text = re.sub(r'<[^>]+>', ' ', html)
309+
text = re.sub(r'\s+', ' ', text).strip()
310+
return {'text': text[:10000]} # Cap at 10k chars
311+
312+
elif mode == 'links':
313+
links = re.findall(
314+
r'<a[^>]+href=["\']([^"\']+)["\'][^>]*>(.*?)</a>',
315+
html, re.IGNORECASE | re.DOTALL
316+
)
317+
return {'links': [
318+
{'url': l[0],
319+
'text': re.sub(r'<[^>]+>', '', l[1]).strip()}
320+
for l in links if l[0].startswith('http')
321+
][:50]} # Cap at 50 links
322+
323+
elif mode == 'forms':
324+
forms = re.findall(
325+
r'<form[^>]*>(.*?)</form>',
326+
html, re.IGNORECASE | re.DOTALL
327+
)
328+
inputs = re.findall(
329+
r'<input[^>]+name=["\']([^"\']+)["\'][^>]*>',
330+
html, re.IGNORECASE
331+
)
332+
return {'forms': len(forms), 'inputs': inputs[:20]}
333+
334+
elif mode == 'full':
335+
text = re.sub(r'<[^>]+>', ' ', html)
336+
text = re.sub(r'\s+', ' ', text).strip()
337+
links = re.findall(
338+
r'href=["\']([^"\']+)["\']',
339+
html, re.IGNORECASE
340+
)
341+
return {
342+
'text': text[:10000],
343+
'links': [l for l in links
344+
if l.startswith('http')][:50]
345+
}
346+
347+
return {'raw': html[:5000]}
348+
215349
# =============================================================================
216350
# Factory function for orchestrator import
217351
# =============================================================================
@@ -251,12 +385,20 @@ def create_os_controller(shared_memory: Dict,
251385
)
252386
print(f"Status: {result['status']}")
253387

254-
# Test 3: Delete file (should require confirmation)
388+
# Test 3: Semantic fetch (should allow)
389+
print("\n[TEST 3] Semantic Fetch (should allow)")
390+
result = controller.fetch_url(
391+
"https://cai-os.com",
392+
extract_mode='content'
393+
)
394+
print(f"Status: {result['status']}")
395+
396+
# Test 4: Delete file (should require confirmation)
255397
print("\n[TEST 3] Delete File (confirmation disabled in test)")
256398
result = controller.delete_file("/tmp/caios_test.txt")
257399
print(f"Status: {result['status']}")
258400

259-
# Test 4: High distress context (should increase density)
401+
# Test 5: High distress context (should increase density)
260402
print("\n[TEST 4] High Distress Context (elevated density)")
261403
shared_mem['distress_density'] = 0.8
262404
controller2 = OSController(shared_mem, require_confirmation=False)

0 commit comments

Comments
 (0)