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.
Files changed (120) hide show
  1. package/.continue/agents/new-config.yaml +22 -0
  2. package/AGENT_STEERING.md +36 -0
  3. package/ARCHITECTURE.md +13 -0
  4. package/CHANGELOG.md +97 -0
  5. package/CLI.md +38 -0
  6. package/CONTRIBUTING.md +55 -0
  7. package/INSTALLATION.md +58 -0
  8. package/LICENSE +60 -0
  9. package/PLUGIN_SYSTEM.md +33 -0
  10. package/PYTHON_SDK.md +22 -0
  11. package/QUICKSTART.md +19 -0
  12. package/README.md +385 -0
  13. package/RELEASE_NOTES_v0.1.0.md +281 -0
  14. package/ROADMAP.md +3 -0
  15. package/RUNTIME.md +44 -0
  16. package/SAFETY_MODEL.md +24 -0
  17. package/TESTING.md +35 -0
  18. package/TROUBLESHOOTING.md +30 -0
  19. package/UPGRADE_GUIDE.md +288 -0
  20. package/VS_CODE_EXTENSION.md +47 -0
  21. package/agent-portal.config.json +20 -0
  22. package/apps/desktop/agent-portal-desktop.zip +0 -0
  23. package/apps/desktop/fixtures/local-workflow.html +151 -0
  24. package/apps/desktop/package.json +18 -0
  25. package/apps/desktop/src/main.ts +117 -0
  26. package/apps/desktop/tsconfig.json +8 -0
  27. package/apps/vscode-extension/LICENSE +60 -0
  28. package/apps/vscode-extension/README.md +20 -0
  29. package/apps/vscode-extension/media/agent-portal-logo.png +0 -0
  30. package/apps/vscode-extension/package.json +149 -0
  31. package/apps/vscode-extension/src/extension.ts +614 -0
  32. package/apps/vscode-extension/tsconfig.json +12 -0
  33. package/assets/branding/agent-portal-logo.png +0 -0
  34. package/connectors/chatgpt-tools/README.md +9 -0
  35. package/connectors/claude-mcp-server/README.md +9 -0
  36. package/connectors/gemini-connector/README.md +9 -0
  37. package/connectors/rest-websocket-api/README.md +9 -0
  38. package/docs/MCP_SERVER.md +68 -0
  39. package/docs/architecture.md +214 -0
  40. package/docs/roadmap.md +125 -0
  41. package/package.json +21 -0
  42. package/packages/agent-portal-mcp/README.md +12 -0
  43. package/packages/agent-portal-mcp/agent_portal_mcp/__init__.py +3 -0
  44. package/packages/agent-portal-mcp/agent_portal_mcp/bridge/__init__.py +1 -0
  45. package/packages/agent-portal-mcp/agent_portal_mcp/bridge/runtime_client.py +180 -0
  46. package/packages/agent-portal-mcp/agent_portal_mcp/cli.py +32 -0
  47. package/packages/agent-portal-mcp/agent_portal_mcp/doctor.py +71 -0
  48. package/packages/agent-portal-mcp/agent_portal_mcp/schemas/__init__.py +1 -0
  49. package/packages/agent-portal-mcp/agent_portal_mcp/schemas/actions.py +17 -0
  50. package/packages/agent-portal-mcp/agent_portal_mcp/schemas/results.py +24 -0
  51. package/packages/agent-portal-mcp/agent_portal_mcp/schemas/risk.py +20 -0
  52. package/packages/agent-portal-mcp/agent_portal_mcp/security/__init__.py +1 -0
  53. package/packages/agent-portal-mcp/agent_portal_mcp/security/policy.py +27 -0
  54. package/packages/agent-portal-mcp/agent_portal_mcp/server.py +148 -0
  55. package/packages/agent-portal-mcp/agent_portal_mcp/tool_registry.py +58 -0
  56. package/packages/agent-portal-mcp/agent_portal_mcp/tools/__init__.py +1 -0
  57. package/packages/agent-portal-mcp/agent_portal_mcp/tools/browser.py +89 -0
  58. package/packages/agent-portal-mcp/agent_portal_mcp/tools/common.py +98 -0
  59. package/packages/agent-portal-mcp/agent_portal_mcp/tools/inspection.py +93 -0
  60. package/packages/agent-portal-mcp/agent_portal_mcp/tools/navigation.py +93 -0
  61. package/packages/agent-portal-mcp/agent_portal_mcp/tools/reports.py +34 -0
  62. package/packages/agent-portal-mcp/agent_portal_mcp/tools/steering.py +93 -0
  63. package/packages/agent-portal-mcp/pyproject.toml +20 -0
  64. package/packages/agent-portal-mcp/tests/test_doctor.py +20 -0
  65. package/packages/agent-portal-mcp/tests/test_mcp_server.py +161 -0
  66. package/packages/core/package.json +15 -0
  67. package/packages/core/src/index.ts +1842 -0
  68. package/packages/core/tsconfig.json +8 -0
  69. package/packages/mcp-server/package.json +15 -0
  70. package/packages/mcp-server/src/index.ts +73 -0
  71. package/packages/mcp-server/tsconfig.json +8 -0
  72. package/packages/sdk/package.json +15 -0
  73. package/packages/sdk/src/index.ts +544 -0
  74. package/packages/sdk/tsconfig.json +8 -0
  75. package/plugins/README.md +16 -0
  76. package/plugins/agent-portal-browser/plugin.json +19 -0
  77. package/plugins/agent-portal-python/plugin.json +16 -0
  78. package/plugins/agent-portal-skills/plugin.json +19 -0
  79. package/plugins/agent-portal-vscode/plugin.json +27 -0
  80. package/plugins/example-runtime-plugin/README.md +3 -0
  81. package/plugins/example-runtime-plugin/plugin.json +20 -0
  82. package/plugins/plugin.schema.json +53 -0
  83. package/python/README.md +18 -0
  84. package/python/agent_portal/__init__.py +5 -0
  85. package/python/agent_portal/__main__.py +5 -0
  86. package/python/agent_portal/browser.py +393 -0
  87. package/python/agent_portal/cli.py +164 -0
  88. package/python/agent_portal/config.py +31 -0
  89. package/python/agent_portal/doctor.py +165 -0
  90. package/python/agent_portal/exceptions.py +39 -0
  91. package/python/agent_portal/logging_utils.py +33 -0
  92. package/python/agent_portal/metrics.py +309 -0
  93. package/python/agent_portal/models.py +160 -0
  94. package/python/agent_portal/plugin_system.py +42 -0
  95. package/python/agent_portal/rate_limit.py +253 -0
  96. package/python/agent_portal/runtime.py +739 -0
  97. package/python/agent_portal/server.py +351 -0
  98. package/python/agent_portal/validation.py +299 -0
  99. package/python/pyproject.toml +29 -0
  100. package/python/tests/test_config.py +24 -0
  101. package/python/tests/test_doctor.py +19 -0
  102. package/python/tests/test_metrics.py +180 -0
  103. package/python/tests/test_rate_limit.py +237 -0
  104. package/python/tests/test_runtime.py +122 -0
  105. package/python/tests/test_server.py +53 -0
  106. package/python/tests/test_validation.py +170 -0
  107. package/releases/desktop/agent-portal-desktop/README.md +378 -0
  108. package/releases/desktop/agent-portal-desktop/RELEASE_NOTES.md +14 -0
  109. package/releases/desktop/agent-portal-desktop/assets/branding/agent-portal-logo.png +0 -0
  110. package/releases/desktop/agent-portal-desktop/fixtures/local-workflow.html +151 -0
  111. package/releases/desktop/agent-portal-desktop/launch-agent-portal.bat +4 -0
  112. package/releases/desktop/agent-portal-desktop.zip +0 -0
  113. package/releases/python/agent_portal-0.0.2-py3-none-any.whl +0 -0
  114. package/releases/python/agent_portal-0.0.2.tar.gz +0 -0
  115. package/scripts/package_desktop.mjs +117 -0
  116. package/scripts/release_python.py +46 -0
  117. package/tests/plugin-manifest.test.mjs +26 -0
  118. package/tests/runtime.test.mjs +41 -0
  119. package/tests/vscode-extension.test.mjs +22 -0
  120. 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`.