agent-portal-2 0.1.0
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.
- package/.continue/agents/new-config.yaml +22 -0
- package/AGENT_STEERING.md +36 -0
- package/ARCHITECTURE.md +13 -0
- package/CHANGELOG.md +97 -0
- package/CLI.md +38 -0
- package/CONTRIBUTING.md +55 -0
- package/INSTALLATION.md +58 -0
- package/LICENSE +60 -0
- package/PLUGIN_SYSTEM.md +33 -0
- package/PYTHON_SDK.md +22 -0
- package/QUICKSTART.md +19 -0
- package/README.md +385 -0
- package/RELEASE_NOTES_v0.1.0.md +281 -0
- package/ROADMAP.md +3 -0
- package/RUNTIME.md +44 -0
- package/SAFETY_MODEL.md +24 -0
- package/TESTING.md +35 -0
- package/TROUBLESHOOTING.md +30 -0
- package/UPGRADE_GUIDE.md +288 -0
- package/VS_CODE_EXTENSION.md +47 -0
- package/agent-portal.config.json +20 -0
- package/apps/desktop/agent-portal-desktop.zip +0 -0
- package/apps/desktop/fixtures/local-workflow.html +151 -0
- package/apps/desktop/package.json +18 -0
- package/apps/desktop/src/main.ts +117 -0
- package/apps/desktop/tsconfig.json +8 -0
- package/apps/vscode-extension/LICENSE +60 -0
- package/apps/vscode-extension/README.md +20 -0
- package/apps/vscode-extension/media/agent-portal-logo.png +0 -0
- package/apps/vscode-extension/package.json +149 -0
- package/apps/vscode-extension/src/extension.ts +614 -0
- package/apps/vscode-extension/tsconfig.json +12 -0
- package/assets/branding/agent-portal-logo.png +0 -0
- package/connectors/chatgpt-tools/README.md +9 -0
- package/connectors/claude-mcp-server/README.md +9 -0
- package/connectors/gemini-connector/README.md +9 -0
- package/connectors/rest-websocket-api/README.md +9 -0
- package/docs/MCP_SERVER.md +68 -0
- package/docs/architecture.md +214 -0
- package/docs/roadmap.md +125 -0
- package/package.json +21 -0
- package/packages/agent-portal-mcp/README.md +12 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/__init__.py +3 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/bridge/__init__.py +1 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/bridge/runtime_client.py +180 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/cli.py +32 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/doctor.py +71 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/schemas/__init__.py +1 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/schemas/actions.py +17 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/schemas/results.py +24 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/schemas/risk.py +20 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/security/__init__.py +1 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/security/policy.py +27 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/server.py +148 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/tool_registry.py +58 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/tools/__init__.py +1 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/tools/browser.py +89 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/tools/common.py +98 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/tools/inspection.py +93 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/tools/navigation.py +93 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/tools/reports.py +34 -0
- package/packages/agent-portal-mcp/agent_portal_mcp/tools/steering.py +93 -0
- package/packages/agent-portal-mcp/pyproject.toml +20 -0
- package/packages/agent-portal-mcp/tests/test_doctor.py +20 -0
- package/packages/agent-portal-mcp/tests/test_mcp_server.py +161 -0
- package/packages/core/package.json +15 -0
- package/packages/core/src/index.ts +1842 -0
- package/packages/core/tsconfig.json +8 -0
- package/packages/mcp-server/package.json +15 -0
- package/packages/mcp-server/src/index.ts +73 -0
- package/packages/mcp-server/tsconfig.json +8 -0
- package/packages/sdk/package.json +15 -0
- package/packages/sdk/src/index.ts +544 -0
- package/packages/sdk/tsconfig.json +8 -0
- package/plugins/README.md +16 -0
- package/plugins/agent-portal-browser/plugin.json +19 -0
- package/plugins/agent-portal-python/plugin.json +16 -0
- package/plugins/agent-portal-skills/plugin.json +19 -0
- package/plugins/agent-portal-vscode/plugin.json +27 -0
- package/plugins/example-runtime-plugin/README.md +3 -0
- package/plugins/example-runtime-plugin/plugin.json +20 -0
- package/plugins/plugin.schema.json +53 -0
- package/python/README.md +18 -0
- package/python/agent_portal/__init__.py +5 -0
- package/python/agent_portal/__main__.py +5 -0
- package/python/agent_portal/browser.py +393 -0
- package/python/agent_portal/cli.py +164 -0
- package/python/agent_portal/config.py +31 -0
- package/python/agent_portal/doctor.py +165 -0
- package/python/agent_portal/exceptions.py +39 -0
- package/python/agent_portal/logging_utils.py +33 -0
- package/python/agent_portal/metrics.py +309 -0
- package/python/agent_portal/models.py +160 -0
- package/python/agent_portal/plugin_system.py +42 -0
- package/python/agent_portal/rate_limit.py +253 -0
- package/python/agent_portal/runtime.py +739 -0
- package/python/agent_portal/server.py +351 -0
- package/python/agent_portal/validation.py +299 -0
- package/python/pyproject.toml +29 -0
- package/python/tests/test_config.py +24 -0
- package/python/tests/test_doctor.py +19 -0
- package/python/tests/test_metrics.py +180 -0
- package/python/tests/test_rate_limit.py +237 -0
- package/python/tests/test_runtime.py +122 -0
- package/python/tests/test_server.py +53 -0
- package/python/tests/test_validation.py +170 -0
- package/releases/desktop/agent-portal-desktop/README.md +378 -0
- package/releases/desktop/agent-portal-desktop/RELEASE_NOTES.md +14 -0
- package/releases/desktop/agent-portal-desktop/assets/branding/agent-portal-logo.png +0 -0
- package/releases/desktop/agent-portal-desktop/fixtures/local-workflow.html +151 -0
- package/releases/desktop/agent-portal-desktop/launch-agent-portal.bat +4 -0
- package/releases/desktop/agent-portal-desktop.zip +0 -0
- package/releases/python/agent_portal-0.0.2-py3-none-any.whl +0 -0
- package/releases/python/agent_portal-0.0.2.tar.gz +0 -0
- package/scripts/package_desktop.mjs +117 -0
- package/scripts/release_python.py +46 -0
- package/tests/plugin-manifest.test.mjs +26 -0
- package/tests/runtime.test.mjs +41 -0
- package/tests/vscode-extension.test.mjs +22 -0
- package/tsconfig.base.json +16 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""Tests for input validation module."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
11
|
+
|
|
12
|
+
from agent_portal.validation import (
|
|
13
|
+
validate_url,
|
|
14
|
+
validate_selector,
|
|
15
|
+
validate_script,
|
|
16
|
+
validate_action_type,
|
|
17
|
+
validate_risk_level,
|
|
18
|
+
validate_text_input,
|
|
19
|
+
sanitize_text,
|
|
20
|
+
validate_config,
|
|
21
|
+
ValidationError,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ValidationTests(unittest.TestCase):
|
|
26
|
+
"""Test cases for input validation functions."""
|
|
27
|
+
|
|
28
|
+
def test_validate_url_valid_https(self) -> None:
|
|
29
|
+
result = validate_url("https://example.com")
|
|
30
|
+
self.assertTrue(result.is_valid)
|
|
31
|
+
self.assertEqual(result.errors, [])
|
|
32
|
+
|
|
33
|
+
def test_validate_url_valid_http(self) -> None:
|
|
34
|
+
result = validate_url("http://localhost:3000")
|
|
35
|
+
self.assertTrue(result.is_valid)
|
|
36
|
+
self.assertEqual(result.errors, [])
|
|
37
|
+
|
|
38
|
+
def test_validate_url_missing_protocol(self) -> None:
|
|
39
|
+
result = validate_url("example.com")
|
|
40
|
+
self.assertFalse(result.is_valid)
|
|
41
|
+
self.assertIn("protocol", result.errors[0].lower())
|
|
42
|
+
|
|
43
|
+
def test_validate_url_dangerous_protocol(self) -> None:
|
|
44
|
+
result = validate_url("file:///etc/passwd")
|
|
45
|
+
self.assertFalse(result.is_valid)
|
|
46
|
+
self.assertTrue(any("protocol" in err.lower() for err in result.errors))
|
|
47
|
+
|
|
48
|
+
def test_validate_url_javascript(self) -> None:
|
|
49
|
+
result = validate_url("javascript:alert('xss')")
|
|
50
|
+
self.assertFalse(result.is_valid)
|
|
51
|
+
self.assertTrue(any("dangerous" in err.lower() for err in result.errors))
|
|
52
|
+
|
|
53
|
+
def test_validate_url_empty(self) -> None:
|
|
54
|
+
result = validate_url("")
|
|
55
|
+
self.assertFalse(result.is_valid)
|
|
56
|
+
|
|
57
|
+
def test_validate_url_localhost_blocked(self) -> None:
|
|
58
|
+
result = validate_url("http://localhost:8080", allow_local=False)
|
|
59
|
+
self.assertFalse(result.is_valid)
|
|
60
|
+
self.assertTrue(any("localhost" in err.lower() for err in result.errors))
|
|
61
|
+
|
|
62
|
+
def test_validate_selector_valid_css(self) -> None:
|
|
63
|
+
result = validate_selector("#submit-button")
|
|
64
|
+
self.assertTrue(result.is_valid)
|
|
65
|
+
|
|
66
|
+
def test_validate_selector_xss_pattern(self) -> None:
|
|
67
|
+
result = validate_selector("<script>alert('xss')</script>")
|
|
68
|
+
self.assertFalse(result.is_valid)
|
|
69
|
+
self.assertTrue(any("dangerous" in err.lower() for err in result.errors))
|
|
70
|
+
|
|
71
|
+
def test_validate_selector_too_long(self) -> None:
|
|
72
|
+
long_selector = "#" + "a" * 1001
|
|
73
|
+
result = validate_selector(long_selector)
|
|
74
|
+
self.assertFalse(result.is_valid)
|
|
75
|
+
self.assertTrue(any("too long" in err.lower() for err in result.errors))
|
|
76
|
+
|
|
77
|
+
def test_validate_selector_none(self) -> None:
|
|
78
|
+
result = validate_selector(None)
|
|
79
|
+
self.assertTrue(result.is_valid)
|
|
80
|
+
|
|
81
|
+
def test_validate_script_basic(self) -> None:
|
|
82
|
+
result = validate_script("document.querySelector('div')")
|
|
83
|
+
self.assertTrue(result.is_valid)
|
|
84
|
+
|
|
85
|
+
def test_validate_script_dangerous_operations(self) -> None:
|
|
86
|
+
result = validate_script("eval('malicious code')")
|
|
87
|
+
self.assertFalse(result.is_valid)
|
|
88
|
+
self.assertTrue(any("dangerous" in err.lower() for err in result.errors))
|
|
89
|
+
|
|
90
|
+
def test_validate_script_too_long(self) -> None:
|
|
91
|
+
long_script = "console.log('" + "a" * 10001 + "')"
|
|
92
|
+
result = validate_script(long_script)
|
|
93
|
+
self.assertFalse(result.is_valid)
|
|
94
|
+
|
|
95
|
+
def test_validate_action_type_valid(self) -> None:
|
|
96
|
+
for action_type in ["click", "type", "open_url", "screenshot"]:
|
|
97
|
+
result = validate_action_type(action_type)
|
|
98
|
+
self.assertTrue(result.is_valid, f"Failed for {action_type}")
|
|
99
|
+
|
|
100
|
+
def test_validate_action_type_invalid(self) -> None:
|
|
101
|
+
result = validate_action_type("hacking")
|
|
102
|
+
self.assertFalse(result.is_valid)
|
|
103
|
+
self.assertIn("Unknown action type", result.errors[0])
|
|
104
|
+
|
|
105
|
+
def test_validate_risk_level_valid(self) -> None:
|
|
106
|
+
for level in ["safe", "low", "medium", "high", "blocked"]:
|
|
107
|
+
result = validate_risk_level(level)
|
|
108
|
+
self.assertTrue(result.is_valid, f"Failed for {level}")
|
|
109
|
+
|
|
110
|
+
def test_validate_risk_level_invalid(self) -> None:
|
|
111
|
+
result = validate_risk_level("critical")
|
|
112
|
+
self.assertFalse(result.is_valid)
|
|
113
|
+
|
|
114
|
+
def test_validate_text_input_valid(self) -> None:
|
|
115
|
+
result = validate_text_input("Hello, World!")
|
|
116
|
+
self.assertTrue(result.is_valid)
|
|
117
|
+
|
|
118
|
+
def test_validate_text_input_too_long(self) -> None:
|
|
119
|
+
result = validate_text_input("a" * 501, max_length=500)
|
|
120
|
+
self.assertFalse(result.is_valid)
|
|
121
|
+
|
|
122
|
+
def test_sanitize_text_basic(self) -> None:
|
|
123
|
+
result = sanitize_text(" Hello ")
|
|
124
|
+
self.assertEqual(result, "Hello")
|
|
125
|
+
|
|
126
|
+
def test_sanitize_text_null_bytes(self) -> None:
|
|
127
|
+
result = sanitize_text("Hello\x00World")
|
|
128
|
+
self.assertEqual(result, "HelloWorld")
|
|
129
|
+
|
|
130
|
+
def test_sanitize_text_control_characters(self) -> None:
|
|
131
|
+
result = sanitize_text("Hello\x01World")
|
|
132
|
+
self.assertEqual(result, "HelloWorld")
|
|
133
|
+
|
|
134
|
+
def test_sanitize_text_newlines_preserved(self) -> None:
|
|
135
|
+
result = sanitize_text("Hello\nWorld")
|
|
136
|
+
self.assertEqual(result, "Hello\nWorld")
|
|
137
|
+
|
|
138
|
+
def test_sanitize_text_none(self) -> None:
|
|
139
|
+
result = sanitize_text(None)
|
|
140
|
+
self.assertEqual(result, "")
|
|
141
|
+
|
|
142
|
+
def test_validate_config_valid(self) -> None:
|
|
143
|
+
config = {
|
|
144
|
+
"runtime_host": "127.0.0.1",
|
|
145
|
+
"runtime_port": 8765,
|
|
146
|
+
"action_mode": "assisted",
|
|
147
|
+
"approval_policy": "medium",
|
|
148
|
+
}
|
|
149
|
+
result = validate_config(config)
|
|
150
|
+
self.assertTrue(result.is_valid)
|
|
151
|
+
|
|
152
|
+
def test_validate_config_invalid_host(self) -> None:
|
|
153
|
+
config = {"runtime_host": "0.0.0.0"}
|
|
154
|
+
result = validate_config(config)
|
|
155
|
+
self.assertFalse(result.is_valid)
|
|
156
|
+
self.assertTrue(any("security" in err.lower() or "0.0.0.0" in err for err in result.errors))
|
|
157
|
+
|
|
158
|
+
def test_validate_config_invalid_port(self) -> None:
|
|
159
|
+
config = {"runtime_port": 80}
|
|
160
|
+
result = validate_config(config)
|
|
161
|
+
self.assertFalse(result.is_valid)
|
|
162
|
+
|
|
163
|
+
def test_validate_config_invalid_action_mode(self) -> None:
|
|
164
|
+
config = {"action_mode": "dangerous"}
|
|
165
|
+
result = validate_config(config)
|
|
166
|
+
self.assertFalse(result.is_valid)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
if __name__ == "__main__":
|
|
170
|
+
unittest.main()
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/branding/agent-portal-logo.png" alt="Agent Portal Logo" width="420" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# Agent Portal
|
|
6
|
+
|
|
7
|
+
Agent Portal is a desktop-native operating environment for AI agents.
|
|
8
|
+
|
|
9
|
+
Instead of limiting an LLM to code generation, Agent Portal gives it a controlled visual workspace where it can understand, navigate, test, and interact with real user interfaces, local applications, browser sessions, development environments, and project ecosystems.
|
|
10
|
+
|
|
11
|
+
## Vision
|
|
12
|
+
|
|
13
|
+
Give AI agents eyes, hands, memory, context, and permissions.
|
|
14
|
+
|
|
15
|
+
That means combining:
|
|
16
|
+
|
|
17
|
+
- visual understanding
|
|
18
|
+
- browser and desktop control
|
|
19
|
+
- long-lived workspace memory
|
|
20
|
+
- multi-agent orchestration
|
|
21
|
+
- test and reporting workflows
|
|
22
|
+
- secure execution boundaries
|
|
23
|
+
|
|
24
|
+
## What Exists Today
|
|
25
|
+
|
|
26
|
+
The project now has a real local runtime foundation rather than just a concept scaffold. The current repository includes:
|
|
27
|
+
|
|
28
|
+
- a Python-first local runtime in `python/agent_portal`
|
|
29
|
+
- Playwright-backed browser control for open, click, type, hover, scroll, wait, inspect, screenshot, execute, and text reading
|
|
30
|
+
- a local HTTP runtime server for health, status, control, browser, and report routes
|
|
31
|
+
- an agent steering and policy layer with pause, resume, stop, queue approval, blocked actions, and risk-aware behavior
|
|
32
|
+
- report generation with runtime state, actions, risk events, screenshots, and reproduction steps
|
|
33
|
+
- plugin manifest discovery and validation
|
|
34
|
+
- a VS Code extension control center that talks directly to the Python runtime
|
|
35
|
+
- a TypeScript SDK surface that is being shifted into a client of the Python runtime
|
|
36
|
+
- connector scaffolds for ChatGPT-style tools, Claude MCP, Gemini, and generic REST/WebSocket integration
|
|
37
|
+
- a desktop demo surface for local runtime verification
|
|
38
|
+
- documentation for installation, quickstart, runtime, CLI, safety, testing, plugins, and architecture
|
|
39
|
+
|
|
40
|
+
## Core Direction
|
|
41
|
+
|
|
42
|
+
The strongest current architectural direction is:
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
Agent Portal
|
|
46
|
+
│
|
|
47
|
+
├── agent-portal Python package
|
|
48
|
+
│ ├── local runtime owner
|
|
49
|
+
│ ├── Playwright browser/session owner
|
|
50
|
+
│ ├── control and safety policy engine
|
|
51
|
+
│ ├── HTTP API server
|
|
52
|
+
│ └── reporting and plugin validation
|
|
53
|
+
│
|
|
54
|
+
├── VS Code extension
|
|
55
|
+
│ └── developer-facing control panel
|
|
56
|
+
│
|
|
57
|
+
├── TypeScript SDK
|
|
58
|
+
│ └── client wrapper for the Python runtime
|
|
59
|
+
│
|
|
60
|
+
└── Agent connectors
|
|
61
|
+
├── ChatGPT tools
|
|
62
|
+
├── Claude MCP server
|
|
63
|
+
├── Gemini connector
|
|
64
|
+
└── REST/WebSocket API
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The key principle is that runtime and browser session ownership should live in the Python runtime server, while editor tooling, SDKs, and connectors should act as clients of that runtime.
|
|
68
|
+
|
|
69
|
+
## Repo Layout
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
agent-portal.config.json Runtime configuration
|
|
73
|
+
assets/
|
|
74
|
+
branding/ Shared logo and visual brand assets
|
|
75
|
+
apps/
|
|
76
|
+
desktop/ Desktop runtime demo and proving ground
|
|
77
|
+
vscode-extension/ Developer control panel
|
|
78
|
+
connectors/
|
|
79
|
+
chatgpt-tools/ ChatGPT-facing connector direction
|
|
80
|
+
claude-mcp-server/ Claude MCP integration direction
|
|
81
|
+
gemini-connector/ Gemini integration direction
|
|
82
|
+
rest-websocket-api/ Generic transport direction
|
|
83
|
+
docs/
|
|
84
|
+
architecture.md System design and boundaries
|
|
85
|
+
roadmap.md Suggested phased delivery plan
|
|
86
|
+
packages/
|
|
87
|
+
core/ Shared TypeScript contracts and intelligence helpers
|
|
88
|
+
sdk/ Runtime client SDK
|
|
89
|
+
mcp-server/ Tool-facing MCP bridge surface
|
|
90
|
+
plugins/
|
|
91
|
+
*/plugin.json Plugin manifests and examples
|
|
92
|
+
python/
|
|
93
|
+
agent_portal/ Local runtime, browser control, CLI, doctor, server
|
|
94
|
+
tests/ Python runtime test suite
|
|
95
|
+
tests/
|
|
96
|
+
*.test.mjs Workspace-level Node tests
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Runtime Capabilities
|
|
100
|
+
|
|
101
|
+
The local Python runtime currently covers these areas:
|
|
102
|
+
|
|
103
|
+
- startup validation and single-instance locking
|
|
104
|
+
- runtime health checks and doctor diagnostics
|
|
105
|
+
- browser launch and cleanup
|
|
106
|
+
- browser action execution with structured errors
|
|
107
|
+
- policy-aware action approval and blocking
|
|
108
|
+
- screenshot evidence capture
|
|
109
|
+
- report generation
|
|
110
|
+
- plugin manifest validation
|
|
111
|
+
- localhost-first serving with optional bearer token auth
|
|
112
|
+
|
|
113
|
+
### Runtime HTTP Routes
|
|
114
|
+
|
|
115
|
+
- `GET /health`
|
|
116
|
+
- `GET /status`
|
|
117
|
+
- `GET /report/latest`
|
|
118
|
+
- `POST /control/start`
|
|
119
|
+
- `POST /control/stop`
|
|
120
|
+
- `POST /control/pause`
|
|
121
|
+
- `POST /control/resume`
|
|
122
|
+
- `POST /control/restart`
|
|
123
|
+
- `POST /control/goal`
|
|
124
|
+
- `POST /control/approve-next`
|
|
125
|
+
- `POST /control/reject-next`
|
|
126
|
+
- `POST /browser/start`
|
|
127
|
+
- `POST /browser/open`
|
|
128
|
+
- `POST /browser/click`
|
|
129
|
+
- `POST /browser/type`
|
|
130
|
+
- `POST /browser/scroll`
|
|
131
|
+
- `POST /browser/hover`
|
|
132
|
+
- `POST /browser/wait`
|
|
133
|
+
- `POST /browser/screenshot`
|
|
134
|
+
- `POST /browser/capture`
|
|
135
|
+
- `POST /browser/inspect`
|
|
136
|
+
- `POST /browser/read-text`
|
|
137
|
+
- `POST /browser/execute`
|
|
138
|
+
- `POST /report/generate`
|
|
139
|
+
|
|
140
|
+
## Agent Steering
|
|
141
|
+
|
|
142
|
+
The current steering model is focused on keeping the runtime usable and safe while still allowing automation:
|
|
143
|
+
|
|
144
|
+
- pause agent execution
|
|
145
|
+
- resume execution
|
|
146
|
+
- stop execution
|
|
147
|
+
- inspect pending actions
|
|
148
|
+
- approve next pending action
|
|
149
|
+
- reject next pending action
|
|
150
|
+
- assign or redirect current goal
|
|
151
|
+
- risk-score actions
|
|
152
|
+
- block password typing
|
|
153
|
+
- block billing and payment-style actions
|
|
154
|
+
- escalate destructive actions
|
|
155
|
+
|
|
156
|
+
The longer-term target is a fuller steering layer with richer action editing, manual override states, and live queue streaming.
|
|
157
|
+
|
|
158
|
+
## Getting Started
|
|
159
|
+
|
|
160
|
+
1. Install Node dependencies:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
npm install
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
2. Install Playwright browser binaries:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
npx playwright install chromium
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
3. Install the Python runtime package:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
pip install -e ./python
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
4. Run a health check:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
agent-portal doctor
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
5. Start the Python runtime:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
agent-portal start
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
6. In another terminal, run the desktop demo:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
npm run dev --workspace @agent-portal/desktop
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
7. Open the VS Code extension sidebar and connect to the runtime.
|
|
197
|
+
|
|
198
|
+
## Developer Workflow
|
|
199
|
+
|
|
200
|
+
Typical local workflow:
|
|
201
|
+
|
|
202
|
+
1. Start your local app on something like `localhost:3000` or `localhost:5173`.
|
|
203
|
+
2. Start Agent Portal with `agent-portal start`.
|
|
204
|
+
3. Connect the VS Code extension to `http://127.0.0.1:8765`.
|
|
205
|
+
4. Use the runtime or SDK to open the app, inspect the page, and drive actions.
|
|
206
|
+
5. Capture screenshots and reports for QA or debugging.
|
|
207
|
+
6. Review blocked or pending actions through the control surface.
|
|
208
|
+
|
|
209
|
+
## VS Code Extension
|
|
210
|
+
|
|
211
|
+
The VS Code extension lives in `apps/vscode-extension` and is designed to be the developer-facing control panel.
|
|
212
|
+
|
|
213
|
+
Official extension link:
|
|
214
|
+
|
|
215
|
+
- [Agent Portal on the Visual Studio Marketplace](https://marketplace.visualstudio.com/manage/publishers/magnificent-language/extensions/agent-portal/hub)
|
|
216
|
+
|
|
217
|
+
It currently provides:
|
|
218
|
+
|
|
219
|
+
- a branded sidebar view
|
|
220
|
+
- runtime start, stop, and restart commands
|
|
221
|
+
- runtime polling and status display
|
|
222
|
+
- pending action queue display
|
|
223
|
+
- approve/reject controls
|
|
224
|
+
- current goal display
|
|
225
|
+
- local dev server detection
|
|
226
|
+
- quick access to reports and docs
|
|
227
|
+
|
|
228
|
+
Important settings:
|
|
229
|
+
|
|
230
|
+
- `agentPortal.runtimeUrl`
|
|
231
|
+
- `agentPortal.preferredLocalDevPort`
|
|
232
|
+
|
|
233
|
+
## SDK And Connectors
|
|
234
|
+
|
|
235
|
+
The TypeScript SDK is shifting toward a thin client model that targets the Python runtime instead of owning browser sessions itself.
|
|
236
|
+
|
|
237
|
+
Connector direction:
|
|
238
|
+
|
|
239
|
+
- ChatGPT tools should translate tool calls into runtime API actions
|
|
240
|
+
- Claude MCP should expose runtime tools and reports over MCP
|
|
241
|
+
- Gemini connector should mirror the same runtime contract
|
|
242
|
+
- REST/WebSocket connector should become the stable integration boundary for all external clients
|
|
243
|
+
|
|
244
|
+
## Using Agent Portal With MCP
|
|
245
|
+
|
|
246
|
+
Agent Portal now includes a Python MCP bridge package under `packages/agent-portal-mcp`.
|
|
247
|
+
|
|
248
|
+
Basic flow:
|
|
249
|
+
|
|
250
|
+
1. Start the runtime:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
agent-portal start
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
2. Start the MCP server:
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
agent-portal mcp start
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
3. Connect an AI client that supports MCP to the local Agent Portal MCP server.
|
|
263
|
+
|
|
264
|
+
The MCP server exposes browser, navigation, inspection, steering, and report tools while routing risky actions through the Agent Portal approval system.
|
|
265
|
+
|
|
266
|
+
## Plugins
|
|
267
|
+
|
|
268
|
+
The plugin model is manifest-driven.
|
|
269
|
+
|
|
270
|
+
Each plugin can declare:
|
|
271
|
+
|
|
272
|
+
- name
|
|
273
|
+
- version
|
|
274
|
+
- type
|
|
275
|
+
- permissions
|
|
276
|
+
- entry point
|
|
277
|
+
- commands
|
|
278
|
+
- settings
|
|
279
|
+
- panels
|
|
280
|
+
- lifecycle hooks
|
|
281
|
+
|
|
282
|
+
The repository includes example and product-surface plugin manifests under `plugins/`.
|
|
283
|
+
|
|
284
|
+
## Testing
|
|
285
|
+
|
|
286
|
+
Current verification commands:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
python -m compileall python
|
|
290
|
+
python -m unittest discover -s python/tests -v
|
|
291
|
+
npm run check
|
|
292
|
+
npm test
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
These cover:
|
|
296
|
+
|
|
297
|
+
- Python runtime compilation
|
|
298
|
+
- runtime unit tests
|
|
299
|
+
- doctor/config/plugin validation
|
|
300
|
+
- HTTP server behavior
|
|
301
|
+
- workspace TypeScript builds
|
|
302
|
+
- extension manifest expectations
|
|
303
|
+
- local browser/runtime workflow coverage in Node tests
|
|
304
|
+
|
|
305
|
+
## Release Outputs
|
|
306
|
+
|
|
307
|
+
The repo now includes first-pass release packaging flows for both Python and the desktop runtime.
|
|
308
|
+
|
|
309
|
+
### Python Build Artifacts
|
|
310
|
+
|
|
311
|
+
Build Python release artifacts into `releases/python` with:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
npm run release:python
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Expected outputs:
|
|
318
|
+
|
|
319
|
+
- source distribution (`.tar.gz`)
|
|
320
|
+
- wheel (`.whl`)
|
|
321
|
+
|
|
322
|
+
If the `build` module is missing, the script exits with a clear install command.
|
|
323
|
+
|
|
324
|
+
### Desktop Release Package
|
|
325
|
+
|
|
326
|
+
Build a desktop runtime release zip into `releases/desktop` with:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
npm run release:desktop
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
That package includes:
|
|
333
|
+
|
|
334
|
+
- compiled desktop runtime output
|
|
335
|
+
- local workflow fixtures
|
|
336
|
+
- branding assets
|
|
337
|
+
- a Windows launch script
|
|
338
|
+
- release notes
|
|
339
|
+
|
|
340
|
+
## Safety And Reliability
|
|
341
|
+
|
|
342
|
+
Current hardening themes include:
|
|
343
|
+
|
|
344
|
+
- localhost binding by default
|
|
345
|
+
- optional local bearer token auth
|
|
346
|
+
- structured runtime errors
|
|
347
|
+
- duplicate-instance prevention
|
|
348
|
+
- graceful shutdown paths
|
|
349
|
+
- blocked high-risk categories
|
|
350
|
+
- better user-facing diagnostics through `agent-portal doctor`
|
|
351
|
+
- report-based traceability for actions and failures
|
|
352
|
+
|
|
353
|
+
## Documentation
|
|
354
|
+
|
|
355
|
+
Top-level docs available in this repo:
|
|
356
|
+
|
|
357
|
+
- `INSTALLATION.md`
|
|
358
|
+
- `QUICKSTART.md`
|
|
359
|
+
- `CLI.md`
|
|
360
|
+
- `RUNTIME.md`
|
|
361
|
+
- `PYTHON_SDK.md`
|
|
362
|
+
- `VS_CODE_EXTENSION.md`
|
|
363
|
+
- `AGENT_STEERING.md`
|
|
364
|
+
- `PLUGIN_SYSTEM.md`
|
|
365
|
+
- `SAFETY_MODEL.md`
|
|
366
|
+
- `TESTING.md`
|
|
367
|
+
- `TROUBLESHOOTING.md`
|
|
368
|
+
- `ARCHITECTURE.md`
|
|
369
|
+
- `ROADMAP.md`
|
|
370
|
+
|
|
371
|
+
## Near-Term Priorities
|
|
372
|
+
|
|
373
|
+
1. Complete the migration of live session ownership from TypeScript runtime surfaces into the Python runtime server.
|
|
374
|
+
2. Add a broadcast channel for live runtime events so the extension and connectors can stream state instead of polling.
|
|
375
|
+
3. Expand approval flow from "approve next pending action" into richer queued-action execution control.
|
|
376
|
+
4. Expand `VisionCore` from heuristics into a stronger multimodal understanding engine.
|
|
377
|
+
5. Add durable memory retrieval, comparison, and project-aware context reuse.
|
|
378
|
+
6. Extend runtime understanding beyond the browser into desktop applications and developer tools.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Agent Portal Desktop Runtime Package
|
|
2
|
+
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
|
|
5
|
+
Included:
|
|
6
|
+
- desktop runtime build output
|
|
7
|
+
- local workflow fixtures
|
|
8
|
+
- shared branding assets
|
|
9
|
+
- launch-agent-portal.bat helper
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
1. Ensure Node.js is installed on the target machine.
|
|
13
|
+
2. Open a terminal in this package directory.
|
|
14
|
+
3. Run `launch-agent-portal.bat`.
|