frontend-perception-engine 0.1.1__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/PKG-INFO +17 -1
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/README.md +15 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/pyproject.toml +2 -1
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/frontend_perception_engine.egg-info/PKG-INFO +17 -1
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/frontend_perception_engine.egg-info/SOURCES.txt +4 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/frontend_perception_engine.egg-info/requires.txt +1 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/cli/install.py +53 -16
- frontend_perception_engine-0.2.0/src/navigation/mcp/diff.py +68 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/mcp/envelope.py +19 -10
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/mcp/handlers.py +201 -91
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/mcp/instructions.py +4 -2
- frontend_perception_engine-0.2.0/src/navigation/mcp/resources.py +108 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/mcp/server.py +5 -4
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/mcp/tools.py +37 -11
- frontend_perception_engine-0.2.0/src/navigation/mcp/visual_response.py +103 -0
- frontend_perception_engine-0.2.0/src/navigation/perception/observation.py +121 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/scan.py +11 -1
- frontend_perception_engine-0.2.0/src/navigation/perception/visual_capture.py +211 -0
- frontend_perception_engine-0.2.0/src/navigation/perception/visual_diff.py +101 -0
- frontend_perception_engine-0.2.0/src/navigation/perception/visual_insights.py +163 -0
- frontend_perception_engine-0.1.1/src/navigation/mcp/diff.py +0 -28
- frontend_perception_engine-0.1.1/src/navigation/mcp/resources.py +0 -82
- frontend_perception_engine-0.1.1/src/navigation/perception/observation.py +0 -97
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/setup.cfg +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/frontend_perception_engine.egg-info/dependency_links.txt +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/frontend_perception_engine.egg-info/entry_points.txt +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/frontend_perception_engine.egg-info/top_level.txt +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/__init__.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/browser_use/__init__.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/browser_use/agent_runner.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/browser_use/hints.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/browser_use/integration.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/browser_use/llm.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/cli/__init__.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/codeGraph/__init__.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/codeGraph/crg_impl.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/codeGraph/factory.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/codeGraph/interface.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/codeGraph/null_impl.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/mcp/__init__.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/mcp/__main__.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/mcp/scan_registry.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/mcp/session_store.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/__init__.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/artifacts.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/auth_gate.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/budget.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/cdp_hub.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/dev_insights.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/exploration.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/feature_flags.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/file_upload.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/flow_graph.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/form_probe.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/iframe_context.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/preflight.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/rich_editors.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/route_guards.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/runner.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/scripted_actions.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/state_manager.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/verification.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/virtual_scroll.py +0 -0
- {frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/perception/websocket_observer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frontend-perception-engine
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Frontend perception engine with optional CRG-powered navigation hints for Browser Use.
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -8,6 +8,7 @@ Requires-Dist: browser-use>=0.13.3
|
|
|
8
8
|
Requires-Dist: code-review-graph>=2.3.6
|
|
9
9
|
Requires-Dist: python-dotenv>=1.0.0
|
|
10
10
|
Requires-Dist: mcp>=1.0.0
|
|
11
|
+
Requires-Dist: pillow>=10.0.0
|
|
11
12
|
Provides-Extra: aws
|
|
12
13
|
Requires-Dist: boto3>=1.35.0; extra == "aws"
|
|
13
14
|
|
|
@@ -55,12 +56,25 @@ Your coding agent (Cursor/Claude/Codex) remains the brain.
|
|
|
55
56
|
|
|
56
57
|
### Install
|
|
57
58
|
|
|
59
|
+
Both PyPI names install the same MCP server:
|
|
60
|
+
|
|
61
|
+
| Package | Install |
|
|
62
|
+
|---------|---------|
|
|
63
|
+
| `frontend-perception-engine` | `pip install frontend-perception-engine` |
|
|
64
|
+
| `frontend-mcp` (alias) | `pip install frontend-mcp` |
|
|
65
|
+
|
|
58
66
|
Recommended (quiet output + next steps):
|
|
59
67
|
|
|
60
68
|
```bash
|
|
61
69
|
uvx --from frontend-perception-engine frontend-perception-install
|
|
62
70
|
```
|
|
63
71
|
|
|
72
|
+
Or the shorter alias name:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
uvx --from frontend-mcp frontend-mcp-install
|
|
76
|
+
```
|
|
77
|
+
|
|
64
78
|
With Chromium for Browser Use:
|
|
65
79
|
|
|
66
80
|
```bash
|
|
@@ -97,6 +111,8 @@ Using `uvx` (no local install in current environment):
|
|
|
97
111
|
|
|
98
112
|
```bash
|
|
99
113
|
uvx --from frontend-perception-engine frontend-perception-mcp
|
|
114
|
+
# or
|
|
115
|
+
uvx --from frontend-mcp frontend-mcp
|
|
100
116
|
```
|
|
101
117
|
|
|
102
118
|
### Cursor MCP config
|
|
@@ -42,12 +42,25 @@ Your coding agent (Cursor/Claude/Codex) remains the brain.
|
|
|
42
42
|
|
|
43
43
|
### Install
|
|
44
44
|
|
|
45
|
+
Both PyPI names install the same MCP server:
|
|
46
|
+
|
|
47
|
+
| Package | Install |
|
|
48
|
+
|---------|---------|
|
|
49
|
+
| `frontend-perception-engine` | `pip install frontend-perception-engine` |
|
|
50
|
+
| `frontend-mcp` (alias) | `pip install frontend-mcp` |
|
|
51
|
+
|
|
45
52
|
Recommended (quiet output + next steps):
|
|
46
53
|
|
|
47
54
|
```bash
|
|
48
55
|
uvx --from frontend-perception-engine frontend-perception-install
|
|
49
56
|
```
|
|
50
57
|
|
|
58
|
+
Or the shorter alias name:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
uvx --from frontend-mcp frontend-mcp-install
|
|
62
|
+
```
|
|
63
|
+
|
|
51
64
|
With Chromium for Browser Use:
|
|
52
65
|
|
|
53
66
|
```bash
|
|
@@ -84,6 +97,8 @@ Using `uvx` (no local install in current environment):
|
|
|
84
97
|
|
|
85
98
|
```bash
|
|
86
99
|
uvx --from frontend-perception-engine frontend-perception-mcp
|
|
100
|
+
# or
|
|
101
|
+
uvx --from frontend-mcp frontend-mcp
|
|
87
102
|
```
|
|
88
103
|
|
|
89
104
|
### Cursor MCP config
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "frontend-perception-engine"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.0"
|
|
4
4
|
description = "Frontend perception engine with optional CRG-powered navigation hints for Browser Use."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -9,6 +9,7 @@ dependencies = [
|
|
|
9
9
|
"code-review-graph>=2.3.6",
|
|
10
10
|
"python-dotenv>=1.0.0",
|
|
11
11
|
"mcp>=1.0.0",
|
|
12
|
+
"pillow>=10.0.0",
|
|
12
13
|
]
|
|
13
14
|
|
|
14
15
|
[project.scripts]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frontend-perception-engine
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Frontend perception engine with optional CRG-powered navigation hints for Browser Use.
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -8,6 +8,7 @@ Requires-Dist: browser-use>=0.13.3
|
|
|
8
8
|
Requires-Dist: code-review-graph>=2.3.6
|
|
9
9
|
Requires-Dist: python-dotenv>=1.0.0
|
|
10
10
|
Requires-Dist: mcp>=1.0.0
|
|
11
|
+
Requires-Dist: pillow>=10.0.0
|
|
11
12
|
Provides-Extra: aws
|
|
12
13
|
Requires-Dist: boto3>=1.35.0; extra == "aws"
|
|
13
14
|
|
|
@@ -55,12 +56,25 @@ Your coding agent (Cursor/Claude/Codex) remains the brain.
|
|
|
55
56
|
|
|
56
57
|
### Install
|
|
57
58
|
|
|
59
|
+
Both PyPI names install the same MCP server:
|
|
60
|
+
|
|
61
|
+
| Package | Install |
|
|
62
|
+
|---------|---------|
|
|
63
|
+
| `frontend-perception-engine` | `pip install frontend-perception-engine` |
|
|
64
|
+
| `frontend-mcp` (alias) | `pip install frontend-mcp` |
|
|
65
|
+
|
|
58
66
|
Recommended (quiet output + next steps):
|
|
59
67
|
|
|
60
68
|
```bash
|
|
61
69
|
uvx --from frontend-perception-engine frontend-perception-install
|
|
62
70
|
```
|
|
63
71
|
|
|
72
|
+
Or the shorter alias name:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
uvx --from frontend-mcp frontend-mcp-install
|
|
76
|
+
```
|
|
77
|
+
|
|
64
78
|
With Chromium for Browser Use:
|
|
65
79
|
|
|
66
80
|
```bash
|
|
@@ -97,6 +111,8 @@ Using `uvx` (no local install in current environment):
|
|
|
97
111
|
|
|
98
112
|
```bash
|
|
99
113
|
uvx --from frontend-perception-engine frontend-perception-mcp
|
|
114
|
+
# or
|
|
115
|
+
uvx --from frontend-mcp frontend-mcp
|
|
100
116
|
```
|
|
101
117
|
|
|
102
118
|
### Cursor MCP config
|
|
@@ -30,6 +30,7 @@ src/navigation/mcp/scan_registry.py
|
|
|
30
30
|
src/navigation/mcp/server.py
|
|
31
31
|
src/navigation/mcp/session_store.py
|
|
32
32
|
src/navigation/mcp/tools.py
|
|
33
|
+
src/navigation/mcp/visual_response.py
|
|
33
34
|
src/navigation/perception/__init__.py
|
|
34
35
|
src/navigation/perception/artifacts.py
|
|
35
36
|
src/navigation/perception/auth_gate.py
|
|
@@ -52,4 +53,7 @@ src/navigation/perception/scripted_actions.py
|
|
|
52
53
|
src/navigation/perception/state_manager.py
|
|
53
54
|
src/navigation/perception/verification.py
|
|
54
55
|
src/navigation/perception/virtual_scroll.py
|
|
56
|
+
src/navigation/perception/visual_capture.py
|
|
57
|
+
src/navigation/perception/visual_diff.py
|
|
58
|
+
src/navigation/perception/visual_insights.py
|
|
55
59
|
src/navigation/perception/websocket_observer.py
|
{frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/cli/install.py
RENAMED
|
@@ -45,22 +45,47 @@ class _Spinner:
|
|
|
45
45
|
time.sleep(0.1)
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
def
|
|
49
|
-
|
|
50
|
-
sys.executable,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
cmd.append('--upgrade')
|
|
48
|
+
def _pip_available() -> bool:
|
|
49
|
+
result = subprocess.run(
|
|
50
|
+
[sys.executable, '-m', 'pip', '--version'],
|
|
51
|
+
capture_output=True,
|
|
52
|
+
)
|
|
53
|
+
return result.returncode == 0
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _build_install_command(*, upgrade: bool, editable: str | None) -> list[str]:
|
|
57
|
+
target: list[str]
|
|
59
58
|
if editable is not None:
|
|
60
|
-
|
|
59
|
+
target = ['-e', editable]
|
|
61
60
|
else:
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
target = [PACKAGE_NAME]
|
|
62
|
+
|
|
63
|
+
if _pip_available():
|
|
64
|
+
cmd = [
|
|
65
|
+
sys.executable,
|
|
66
|
+
'-m',
|
|
67
|
+
'pip',
|
|
68
|
+
'install',
|
|
69
|
+
'-q',
|
|
70
|
+
'--disable-pip-version-check',
|
|
71
|
+
]
|
|
72
|
+
if upgrade:
|
|
73
|
+
cmd.append('--upgrade')
|
|
74
|
+
cmd.extend(target)
|
|
75
|
+
return cmd
|
|
76
|
+
|
|
77
|
+
uv = shutil.which('uv')
|
|
78
|
+
if uv is not None:
|
|
79
|
+
cmd = [uv, 'pip', 'install', '-q']
|
|
80
|
+
if upgrade:
|
|
81
|
+
cmd.append('--upgrade')
|
|
82
|
+
cmd.extend(target)
|
|
83
|
+
return cmd
|
|
84
|
+
|
|
85
|
+
raise SystemExit(
|
|
86
|
+
'No installer available. Install pip or uv, or use:\n'
|
|
87
|
+
' uvx --from frontend-perception-engine frontend-perception-mcp\n',
|
|
88
|
+
)
|
|
64
89
|
|
|
65
90
|
|
|
66
91
|
def _build_browser_install_command() -> list[str]:
|
|
@@ -102,7 +127,9 @@ def _print_success(*, with_browser: bool) -> None:
|
|
|
102
127
|
sys.stdout.write(' frontend-perception-mcp\n\n')
|
|
103
128
|
sys.stdout.write(' Or with uvx (no global install):\n')
|
|
104
129
|
sys.stdout.write(' uvx --from frontend-perception-engine frontend-perception-mcp\n\n')
|
|
105
|
-
sys.stdout.write('
|
|
130
|
+
sys.stdout.write(' Or shorter PyPI name:\n')
|
|
131
|
+
sys.stdout.write(' uvx --from frontend-mcp frontend-mcp\n\n')
|
|
132
|
+
sys.stdout.write(' Cursor MCP config (either name):\n')
|
|
106
133
|
sys.stdout.write(' {\n')
|
|
107
134
|
sys.stdout.write(' "mcpServers": {\n')
|
|
108
135
|
sys.stdout.write(' "frontend-perception": {\n')
|
|
@@ -111,6 +138,7 @@ def _print_success(*, with_browser: bool) -> None:
|
|
|
111
138
|
sys.stdout.write(' }\n')
|
|
112
139
|
sys.stdout.write(' }\n')
|
|
113
140
|
sys.stdout.write(' }\n')
|
|
141
|
+
sys.stdout.write('\n Alias package: pip install frontend-mcp → frontend-mcp / frontend-mcp-install\n')
|
|
114
142
|
if with_browser:
|
|
115
143
|
sys.stdout.write('\n Chromium is ready for Browser Use.\n')
|
|
116
144
|
sys.stdout.flush()
|
|
@@ -151,7 +179,16 @@ def main(argv: Sequence[str] | None = None) -> None:
|
|
|
151
179
|
editable_path = None
|
|
152
180
|
label = 'Installing frontend-perception-engine'
|
|
153
181
|
|
|
154
|
-
|
|
182
|
+
if (
|
|
183
|
+
not args.upgrade
|
|
184
|
+
and editable_path is None
|
|
185
|
+
and _installed_version() is not None
|
|
186
|
+
and not _pip_available()
|
|
187
|
+
):
|
|
188
|
+
_print_success(with_browser=False)
|
|
189
|
+
return
|
|
190
|
+
|
|
191
|
+
_run_quiet(_build_install_command(upgrade=args.upgrade, editable=editable_path), label=label)
|
|
155
192
|
|
|
156
193
|
if args.with_browser:
|
|
157
194
|
browser_cmd = _build_browser_install_command()
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Compare two observation snapshots by scan_id."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from navigation.perception.visual_diff import VisualDiffResult, diff_screenshot_files
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _blocking_issues(obs: dict[str, Any]) -> list[str]:
|
|
11
|
+
di = obs.get('dev_insights') or {}
|
|
12
|
+
summary = di.get('summary') or {}
|
|
13
|
+
blocking = list(summary.get('blocking_issues') or [])
|
|
14
|
+
visual = obs.get('visual_insights') or {}
|
|
15
|
+
blocking.extend(visual.get('blocking') or [])
|
|
16
|
+
return blocking
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _visual_issues_delta(before: dict[str, Any], after: dict[str, Any]) -> dict[str, list[str]]:
|
|
20
|
+
b_vis = set((before.get('visual_insights') or {}).get('blocking') or [])
|
|
21
|
+
a_vis = set((after.get('visual_insights') or {}).get('blocking') or [])
|
|
22
|
+
return {
|
|
23
|
+
'new_visual_blocking': sorted(a_vis - b_vis),
|
|
24
|
+
'removed_visual_blocking': sorted(b_vis - a_vis),
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def diff_observations(
|
|
29
|
+
before: dict[str, Any],
|
|
30
|
+
after: dict[str, Any],
|
|
31
|
+
*,
|
|
32
|
+
artifacts_dir: Path | None = None,
|
|
33
|
+
scan_id_before: str = '',
|
|
34
|
+
scan_id_after: str = '',
|
|
35
|
+
) -> dict[str, Any]:
|
|
36
|
+
b_block = set(_blocking_issues(before))
|
|
37
|
+
a_block = set(_blocking_issues(after))
|
|
38
|
+
b_dom = str(before.get('dom_text') or '')
|
|
39
|
+
a_dom = str(after.get('dom_text') or '')
|
|
40
|
+
excerpt_len = 500
|
|
41
|
+
visual_delta = _visual_issues_delta(before, after)
|
|
42
|
+
|
|
43
|
+
result: dict[str, Any] = {
|
|
44
|
+
'url_before': before.get('url') or '',
|
|
45
|
+
'url_after': after.get('url') or '',
|
|
46
|
+
'url_changed': (before.get('url') or '') != (after.get('url') or ''),
|
|
47
|
+
'dom_text_changed': b_dom != a_dom,
|
|
48
|
+
'new_blocking_issues': sorted(a_block - b_block),
|
|
49
|
+
'removed_blocking_issues': sorted(b_block - a_block),
|
|
50
|
+
'dom_excerpt_before': b_dom[:excerpt_len],
|
|
51
|
+
'dom_excerpt_after': a_dom[:excerpt_len],
|
|
52
|
+
**visual_delta,
|
|
53
|
+
'visual_diff': None,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
before_shot = before.get('annotated_screenshot_path') or before.get('screenshot_path')
|
|
57
|
+
after_shot = after.get('annotated_screenshot_path') or after.get('screenshot_path')
|
|
58
|
+
if artifacts_dir and before_shot and after_shot:
|
|
59
|
+
prefix = f'{scan_id_before}_vs_{scan_id_after}'.replace('/', '_')[:80]
|
|
60
|
+
vd: VisualDiffResult = diff_screenshot_files(
|
|
61
|
+
before_shot,
|
|
62
|
+
after_shot,
|
|
63
|
+
artifacts_dir / 'diffs',
|
|
64
|
+
prefix=prefix,
|
|
65
|
+
)
|
|
66
|
+
result['visual_diff'] = vd.to_dict()
|
|
67
|
+
|
|
68
|
+
return result
|
{frontend_perception_engine-0.1.1 → frontend_perception_engine-0.2.0}/src/navigation/mcp/envelope.py
RENAMED
|
@@ -38,13 +38,22 @@ def envelope_json(**kwargs: Any) -> str:
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def agent_summary_from_observation(obs_dict: dict[str, Any]) -> dict[str, Any]:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
"""Compact summary for host agent reasoning (no planning hints)."""
|
|
42
|
+
di = obs_dict.get('dev_insights') or {}
|
|
43
|
+
summary = di.get('summary') or {}
|
|
44
|
+
page_meta = di.get('page_meta')
|
|
45
|
+
blocking = list(summary.get('blocking_issues') or [])
|
|
46
|
+
advisory = list(summary.get('advisory_issues') or [])
|
|
47
|
+
visual = obs_dict.get('visual_insights') or {}
|
|
48
|
+
for item in visual.get('blocking') or []:
|
|
49
|
+
if item not in blocking:
|
|
50
|
+
blocking.append(item)
|
|
51
|
+
for item in visual.get('advisory') or []:
|
|
52
|
+
if item not in advisory:
|
|
53
|
+
advisory.append(item)
|
|
54
|
+
return {
|
|
55
|
+
'blocking': blocking,
|
|
56
|
+
'advisory': advisory,
|
|
57
|
+
'page_meta': page_meta,
|
|
58
|
+
'degraded': list(obs_dict.get('degraded') or []) + list(di.get('degraded') or []),
|
|
59
|
+
}
|