ya-environment-relay 0.74.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.
@@ -0,0 +1,169 @@
1
+ docs/source
2
+
3
+ # From https://raw.githubusercontent.com/github/gitignore/main/Python.gitignore
4
+
5
+ # Byte-compiled / optimized / DLL files
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+
10
+ # C extensions
11
+ *.so
12
+
13
+ # Distribution / packaging
14
+ .Python
15
+ build/
16
+ develop-eggs/
17
+ dist/
18
+ downloads/
19
+ eggs/
20
+ .eggs/
21
+ lib/
22
+ !apps/
23
+ !apps/ya-claw-web/
24
+ !apps/ya-claw-web/src/
25
+ !apps/ya-claw-web/src/lib/
26
+ !apps/ya-claw-web/src/lib/**
27
+ lib64/
28
+ parts/
29
+ sdist/
30
+ var/
31
+ wheels/
32
+ share/python-wheels/
33
+ *.egg-info/
34
+ .installed.cfg
35
+ *.egg
36
+ MANIFEST
37
+
38
+ # PyInstaller
39
+ # Usually these files are written by a python script from a template
40
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
41
+ *.manifest
42
+ *.spec
43
+
44
+ # Installer logs
45
+ pip-log.txt
46
+ pip-delete-this-directory.txt
47
+
48
+ # Unit test / coverage reports
49
+ htmlcov/
50
+ .tox/
51
+ .nox/
52
+ .coverage
53
+ .coverage.*
54
+ .cache
55
+ nosetests.xml
56
+ coverage.xml
57
+ *.cover
58
+ *.py,cover
59
+ .hypothesis/
60
+ .pytest_cache/
61
+ cover/
62
+
63
+ # Translations
64
+ *.mo
65
+ *.pot
66
+
67
+ # Django stuff:
68
+ *.log
69
+ local_settings.py
70
+ db.sqlite3
71
+ db.sqlite3-journal
72
+
73
+ # Flask stuff:
74
+ instance/
75
+ .webassets-cache
76
+
77
+ # Scrapy stuff:
78
+ .scrapy
79
+
80
+ # Sphinx documentation
81
+ docs/_build/
82
+
83
+ # PyBuilder
84
+ .pybuilder/
85
+ target/
86
+
87
+ # Jupyter Notebook
88
+ .ipynb_checkpoints
89
+
90
+ # IPython
91
+ profile_default/
92
+ ipython_config.py
93
+
94
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
95
+ __pypackages__/
96
+
97
+ # Celery stuff
98
+ celerybeat-schedule
99
+ celerybeat.pid
100
+
101
+ # SageMath parsed files
102
+ *.sage.py
103
+
104
+ # Environments
105
+ .env
106
+ .yaai/
107
+ **/.yaai/
108
+ .venv
109
+ env/
110
+ venv/
111
+ ENV/
112
+ env.bak/
113
+ venv.bak/
114
+
115
+ # Spyder project settings
116
+ .spyderproject
117
+ .spyproject
118
+
119
+ # Rope project settings
120
+ .ropeproject
121
+
122
+ # mkdocs documentation
123
+ /site
124
+
125
+ # mypy
126
+ .mypy_cache/
127
+ .pyright/
128
+ .dmypy.json
129
+ dmypy.json
130
+
131
+ # Pyre type checker
132
+ .pyre/
133
+
134
+ # pytype static type analyzer
135
+ .pytype/
136
+
137
+ # Cython debug symbols
138
+ cython_debug/
139
+
140
+ # Vscode config files
141
+ # .vscode/
142
+
143
+ # PyCharm
144
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
145
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
146
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
147
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
148
+ #.idea/
149
+
150
+ TO-DO.json
151
+ dev/
152
+ ya_agent_sdk/sandbox/shell/templates/public
153
+
154
+ # Sync automaticlly
155
+ yaacli/yaacli/skills/building-agents
156
+
157
+ # Frontend
158
+ node_modules/
159
+ apps/*/dist/
160
+ !apps/ya-desktop/
161
+ !apps/ya-desktop/src/
162
+ !apps/ya-desktop/src/**
163
+ !apps/ya-desktop/src-tauri/
164
+ !apps/ya-desktop/src-tauri/resources/
165
+ !apps/ya-desktop/src-tauri/resources/uv/
166
+ !apps/ya-desktop/src-tauri/resources/uv/.gitkeep
167
+ apps/ya-desktop/src-tauri/resources/uv/uv
168
+ apps/ya-desktop/src-tauri/resources/uv/uv.exe
169
+ *.tsbuildinfo
@@ -0,0 +1,36 @@
1
+ Metadata-Version: 2.4
2
+ Name: ya-environment-relay
3
+ Version: 0.74.0
4
+ Summary: Provider-neutral relay protocol for YA agent environments
5
+ Project-URL: Repository, https://github.com/wh1isper/ya-mono
6
+ Author-email: wh1isper <jizhongsheng957@gmail.com>
7
+ Keywords: agent,environment,protocol,python,relay
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Requires-Python: <3.14,>=3.11
16
+ Requires-Dist: pydantic>=2.0.0
17
+ Description-Content-Type: text/markdown
18
+
19
+ # ya-environment-relay
20
+
21
+ Provider-neutral relay protocol for YA agent environments.
22
+
23
+ `ya-environment-relay` defines how external execution capabilities are exposed to an agent runtime as Environment components.
24
+
25
+ Capability families:
26
+
27
+ - file operations
28
+ - shell execution
29
+ - custom tools
30
+ - resources
31
+ - artifacts
32
+ - computer use
33
+
34
+ The protocol string is `ya-environment-relay.v1`.
35
+
36
+ See [`spec/`](spec/) for the protocol documents.
@@ -0,0 +1,18 @@
1
+ # ya-environment-relay
2
+
3
+ Provider-neutral relay protocol for YA agent environments.
4
+
5
+ `ya-environment-relay` defines how external execution capabilities are exposed to an agent runtime as Environment components.
6
+
7
+ Capability families:
8
+
9
+ - file operations
10
+ - shell execution
11
+ - custom tools
12
+ - resources
13
+ - artifacts
14
+ - computer use
15
+
16
+ The protocol string is `ya-environment-relay.v1`.
17
+
18
+ See [`spec/`](spec/) for the protocol documents.
@@ -0,0 +1,60 @@
1
+ [project]
2
+ name = "ya-environment-relay"
3
+ dynamic = ["version"]
4
+ description = "Provider-neutral relay protocol for YA agent environments"
5
+ authors = [{ name = "wh1isper", email = "jizhongsheng957@gmail.com" }]
6
+ readme = "README.md"
7
+ keywords = ["python", "agent", "environment", "relay", "protocol"]
8
+ requires-python = ">=3.11,<3.14"
9
+ classifiers = [
10
+ "Intended Audience :: Developers",
11
+ "Programming Language :: Python",
12
+ "Programming Language :: Python :: 3",
13
+ "Programming Language :: Python :: 3.11",
14
+ "Programming Language :: Python :: 3.12",
15
+ "Programming Language :: Python :: 3.13",
16
+ "Topic :: Software Development :: Libraries :: Python Modules",
17
+ ]
18
+
19
+ dependencies = [
20
+ "pydantic>=2.0.0",
21
+ ]
22
+
23
+ [project.urls]
24
+ Repository = "https://github.com/wh1isper/ya-mono"
25
+
26
+ [dependency-groups]
27
+ dev = [
28
+ "deptry>=0.22.0",
29
+ "pyright>=1.1.0",
30
+ "ruff>=0.9.2",
31
+ ]
32
+
33
+ [build-system]
34
+ requires = ["hatchling", "uv-dynamic-versioning>=0.7.0"]
35
+ build-backend = "hatchling.build"
36
+
37
+ [tool.hatch.version]
38
+ source = "uv-dynamic-versioning"
39
+
40
+ [tool.uv-dynamic-versioning]
41
+ vcs = "git"
42
+ style = "pep440"
43
+ bump = true
44
+
45
+ [tool.hatch.build.targets.sdist]
46
+ include = [
47
+ "README.md",
48
+ "pyproject.toml",
49
+ "spec",
50
+ "ya_environment_relay",
51
+ ]
52
+
53
+ [tool.hatch.build.targets.wheel]
54
+ packages = ["ya_environment_relay"]
55
+ force-include = { "spec" = "spec" }
56
+
57
+ [tool.deptry]
58
+ ignore = ["DEP001", "DEP002"]
59
+ package_module_name_map = { "pydantic" = "pydantic", "ya-environment-relay" = "ya_environment_relay" }
60
+ per_rule_ignores = { DEP004 = ["pytest"] }
@@ -0,0 +1,147 @@
1
+ # 01. YA Environment Relay Overview
2
+
3
+ ## Goal
4
+
5
+ YA Environment Relay connects an agent runtime to capabilities that execute in another process, device, sandbox, or host. It turns those external capabilities into `ya-agent-sdk` Environment components so the agent can use them through normal file, shell, resource, and tool abstractions.
6
+
7
+ YA Environment Relay is protocol-level infrastructure. Product integrations such as YA Desktop, YA Claw, cloud workers, or sandbox services implement the protocol for their own deployment models.
8
+
9
+ ## Parties
10
+
11
+ ```mermaid
12
+ flowchart TB
13
+ Runtime[Agent Runtime] --> RelayServer[Relay Server]
14
+ RelayServer <--> RelayClient[Relay Client]
15
+ RelayClient --> Provider[Capability Provider]
16
+ Provider --> Target[Local Device / Sandbox / External System]
17
+
18
+ Runtime --> SDK[ya-agent-sdk Environment]
19
+ SDK --> RelayEnvironment[RelayEnvironment]
20
+ RelayEnvironment --> RelayServer
21
+ ```
22
+
23
+ Definitions:
24
+
25
+ - Agent Runtime: process that runs the model loop and tool calls.
26
+ - Relay Server: endpoint that accepts relay client connections and routes requests.
27
+ - Relay Client: process that connects to the relay server and advertises capabilities.
28
+ - Capability Provider: implementation behind the relay client, such as local filesystem, shell, OS automation, browser, VM, or custom tool host.
29
+ - Relay Environment: SDK Environment implementation backed by relay requests.
30
+
31
+ ## Capability Families
32
+
33
+ YA Environment Relay uses capability families to group provider methods:
34
+
35
+ ```text
36
+ fileops
37
+ shell
38
+ tools
39
+ resources
40
+ artifacts
41
+ computer
42
+ browser
43
+ ```
44
+
45
+ Initial protocol should define the first six families. Browser can be added as a specialized provider or implemented as custom tools.
46
+
47
+ ## Relationship to ya-agent-sdk
48
+
49
+ `ya-agent-sdk` already has core runtime abstractions:
50
+
51
+ - Environment
52
+ - FileOperator
53
+ - Shell
54
+ - ResourceRegistry
55
+ - Toolset
56
+ - resumable resources
57
+
58
+ YA Environment Relay should provide remote implementations of these abstractions:
59
+
60
+ ```python
61
+ RelayEnvironment(Environment)
62
+ RelayFileOperator(FileOperator)
63
+ RelayShell(Shell)
64
+ RelayResourceRegistry(ResourceRegistry)
65
+ RelayToolset(Toolset)
66
+ ```
67
+
68
+ This keeps agent code and profiles stable while moving execution to a connected provider.
69
+
70
+ ## Relationship to Claw
71
+
72
+ Claw can use YA Environment Relay as one `WorkspaceProvider` backend:
73
+
74
+ ```text
75
+ WorkspaceProvider kind = relay
76
+ Environment = RelayEnvironment
77
+ ```
78
+
79
+ Claw remains responsible for:
80
+
81
+ - sessions and runs.
82
+ - profile selection.
83
+ - model execution.
84
+ - HITL approvals.
85
+ - durable trace.
86
+ - artifact storage.
87
+ - provider registry and connection routing.
88
+
89
+ A relay client supplies execution capabilities. Claw exposes them to the agent through SDK abstractions.
90
+
91
+ ## Relationship to Desktop
92
+
93
+ YA Desktop can act as a relay client. It can advertise local capabilities:
94
+
95
+ - selected folders as workspace roots.
96
+ - sandboxed local shell.
97
+ - native OS computer use.
98
+ - Desktop-managed custom tools.
99
+ - local artifact upload.
100
+
101
+ Desktop owns user consent, local grants, and native permission UX. Claw owns runtime authorization and trace.
102
+
103
+ ## Relationship to MCP
104
+
105
+ MCP and YA Environment Relay address overlapping but different surfaces:
106
+
107
+ | Surface | MCP | YA Environment Relay |
108
+ | ------------------------------ | --------------------------- | -------------------- |
109
+ | Tool discovery | yes | yes |
110
+ | JSON Schema tool input | yes | yes |
111
+ | FileOperator abstraction | product-specific | built in |
112
+ | Shell streaming | server-specific | built in |
113
+ | Environment/resource lifecycle | limited by server | built in |
114
+ | Runtime artifact ownership | external or custom | built in |
115
+ | User device relay | possible with custom server | primary use case |
116
+
117
+ A relay client can wrap MCP servers and register selected tools into YA Environment Relay. A Claw profile can use MCP servers and relay capabilities together.
118
+
119
+ ## High-Level Flow
120
+
121
+ ```mermaid
122
+ sequenceDiagram
123
+ participant Client as Relay Client
124
+ participant Server as Relay Server
125
+ participant Runtime as Agent Runtime
126
+ participant Provider as Provider
127
+
128
+ Client->>Server: WebSocket connect
129
+ Client->>Server: hello capabilities
130
+ Server-->>Client: accepted capabilities
131
+ Runtime->>Server: file/shell/tool/computer request
132
+ Server->>Client: relay request
133
+ Client->>Provider: execute
134
+ Provider-->>Client: result / stream
135
+ Client-->>Server: response / stream
136
+ Server-->>Runtime: Environment result
137
+ ```
138
+
139
+ ## Design Principles
140
+
141
+ - The protocol is provider-neutral.
142
+ - The runtime controls model-facing tool exposure.
143
+ - The provider controls local execution and local policy.
144
+ - Capabilities are explicitly advertised and accepted.
145
+ - Streaming and cancellation are first-class.
146
+ - Artifacts are owned by the runtime store when the call belongs to a run.
147
+ - Security is scoped by device, connection, space/workspace, capability, and root grants.
@@ -0,0 +1,376 @@
1
+ # 02. ya-environment-relay.v1 Protocol
2
+
3
+ ## Transport
4
+
5
+ `ya-environment-relay.v1` uses WebSocket as its primary transport. The protocol requires bidirectional request/response, streaming output, cancellation, heartbeat, provider events, and artifact coordination.
6
+
7
+ Connection endpoint shape for a host runtime:
8
+
9
+ ```http
10
+ GET /api/v1/relay/connect
11
+ Authorization: Bearer <relay-token>
12
+ Upgrade: websocket
13
+ ```
14
+
15
+ Products can expose a different path, but the frame format should remain stable.
16
+
17
+ ## Frame Types
18
+
19
+ ```ts
20
+ type RelayFrame =
21
+ | HelloFrame
22
+ | EventFrame
23
+ | RequestFrame
24
+ | ResponseFrame
25
+ | StreamFrame
26
+ | CancelFrame
27
+ | PingFrame
28
+ | PongFrame;
29
+ ```
30
+
31
+ All frames are JSON text frames unless a method explicitly negotiates binary transfer. Large artifacts should use artifact upload methods instead of raw WebSocket binary in the first version.
32
+
33
+ ## Hello
34
+
35
+ The relay client sends `hello` immediately after connection:
36
+
37
+ ```json
38
+ {
39
+ "type": "hello",
40
+ "protocol": "ya-environment-relay.v1",
41
+ "client_id": "client_macbook_123",
42
+ "client_kind": "ya_desktop",
43
+ "client_version": "0.1.0",
44
+ "capabilities": {
45
+ "fileops": {
46
+ "enabled": true,
47
+ "roots": [
48
+ {
49
+ "root_id": "main",
50
+ "label": "ya-mono",
51
+ "virtual_path": "/workspace/main",
52
+ "mode": "rw"
53
+ }
54
+ ]
55
+ },
56
+ "shell": {
57
+ "enabled": true,
58
+ "runtime": "sandboxed_local_shell",
59
+ "interactive": true
60
+ },
61
+ "tools": {
62
+ "enabled": true,
63
+ "tool_count": 2
64
+ },
65
+ "computer": {
66
+ "enabled": true,
67
+ "platform": "macos",
68
+ "screenshots": true,
69
+ "accessibility_tree": true,
70
+ "semantic_actions": true,
71
+ "coordinate_input": true
72
+ }
73
+ }
74
+ }
75
+ ```
76
+
77
+ The relay server responds with an event:
78
+
79
+ ```json
80
+ {
81
+ "type": "event",
82
+ "event": "relay.accepted",
83
+ "payload": {
84
+ "connection_id": "relay_conn_123",
85
+ "accepted_capabilities": ["fileops", "shell", "tools", "computer"],
86
+ "server_time": "2026-05-11T15:40:00Z"
87
+ }
88
+ }
89
+ ```
90
+
91
+ ## Request
92
+
93
+ Either side may send requests when authorized. The most common direction is runtime to provider.
94
+
95
+ ```json
96
+ {
97
+ "type": "request",
98
+ "id": "req_123",
99
+ "method": "file.read",
100
+ "params": {
101
+ "root_id": "main",
102
+ "path": "README.md",
103
+ "encoding": "utf-8"
104
+ },
105
+ "context": {
106
+ "session_id": "session_abc",
107
+ "run_id": "run_def",
108
+ "tool_call_id": "call_ghi"
109
+ }
110
+ }
111
+ ```
112
+
113
+ `id` must be unique within a live connection until the request reaches terminal response or cancellation.
114
+
115
+ ## Response
116
+
117
+ Successful response:
118
+
119
+ ```json
120
+ {
121
+ "type": "response",
122
+ "id": "req_123",
123
+ "result": {
124
+ "content": "# Project\n...",
125
+ "encoding": "utf-8"
126
+ }
127
+ }
128
+ ```
129
+
130
+ Error response:
131
+
132
+ ```json
133
+ {
134
+ "type": "response",
135
+ "id": "req_123",
136
+ "error": {
137
+ "code": "permission_denied",
138
+ "message": "The path is outside the selected roots.",
139
+ "recoverable": true,
140
+ "details": {
141
+ "root_id": "main"
142
+ }
143
+ }
144
+ }
145
+ ```
146
+
147
+ Common error codes:
148
+
149
+ ```text
150
+ invalid_request
151
+ unknown_method
152
+ capability_unavailable
153
+ permission_denied
154
+ approval_required
155
+ policy_blocked
156
+ not_found
157
+ timeout
158
+ cancelled
159
+ provider_error
160
+ relay_disconnected
161
+ artifact_error
162
+ ```
163
+
164
+ ## Stream
165
+
166
+ Long-running requests can emit stream frames before the terminal response.
167
+
168
+ ```json
169
+ {
170
+ "type": "stream",
171
+ "id": "req_shell_1",
172
+ "event": "stdout",
173
+ "data": "Running tests...\n"
174
+ }
175
+ ```
176
+
177
+ Common stream event names:
178
+
179
+ ```text
180
+ stdout
181
+ stderr
182
+ progress
183
+ artifact
184
+ status
185
+ log
186
+ ```
187
+
188
+ Terminal completion uses `response`:
189
+
190
+ ```json
191
+ {
192
+ "type": "response",
193
+ "id": "req_shell_1",
194
+ "result": {
195
+ "exit_code": 0,
196
+ "duration_ms": 1234
197
+ }
198
+ }
199
+ ```
200
+
201
+ ## Cancel
202
+
203
+ Either side can cancel an active request:
204
+
205
+ ```json
206
+ {
207
+ "type": "cancel",
208
+ "id": "req_shell_1",
209
+ "reason": "user_cancelled"
210
+ }
211
+ ```
212
+
213
+ The receiver should attempt cancellation and then send a terminal response:
214
+
215
+ ```json
216
+ {
217
+ "type": "response",
218
+ "id": "req_shell_1",
219
+ "error": {
220
+ "code": "cancelled",
221
+ "message": "Request cancelled by user.",
222
+ "recoverable": true
223
+ }
224
+ }
225
+ ```
226
+
227
+ ## Heartbeat
228
+
229
+ Heartbeat frames keep the connection alive and measure latency.
230
+
231
+ ```json
232
+ {
233
+ "type": "ping",
234
+ "id": "ping_1",
235
+ "ts": "2026-05-11T15:45:00Z"
236
+ }
237
+ ```
238
+
239
+ ```json
240
+ {
241
+ "type": "pong",
242
+ "id": "ping_1",
243
+ "ts": "2026-05-11T15:45:00Z"
244
+ }
245
+ ```
246
+
247
+ ## Events
248
+
249
+ Events are one-way notifications outside request/response.
250
+
251
+ ```json
252
+ {
253
+ "type": "event",
254
+ "event": "capability.updated",
255
+ "payload": {
256
+ "capability": "computer",
257
+ "state": "permission_required"
258
+ }
259
+ }
260
+ ```
261
+
262
+ Common events:
263
+
264
+ ```text
265
+ relay.accepted
266
+ capability.updated
267
+ provider.paused
268
+ provider.resumed
269
+ artifact.uploaded
270
+ tool.registered
271
+ tool.unregistered
272
+ resource.updated
273
+ ```
274
+
275
+ ## Method Namespaces
276
+
277
+ ```text
278
+ file.read
279
+ file.write
280
+ file.list
281
+ file.stat
282
+ file.mkdir
283
+ file.delete
284
+ file.search
285
+ file.watch
286
+
287
+ shell.start
288
+ shell.input
289
+ shell.resize
290
+ shell.signal
291
+ shell.cancel
292
+ shell.status
293
+
294
+ tool.list
295
+ tool.register
296
+ tool.unregister
297
+ tool.call
298
+ tool.cancel
299
+
300
+ resource.list
301
+ resource.get
302
+ resource.create
303
+ resource.dispose
304
+ resource.export_state
305
+ resource.restore_state
306
+
307
+ computer.status
308
+ computer.see
309
+ computer.act
310
+ computer.pause
311
+ computer.resume
312
+ computer.takeover
313
+ computer.release
314
+
315
+ artifact.reserve
316
+ artifact.upload
317
+ artifact.complete
318
+ artifact.abort
319
+ ```
320
+
321
+ ## Artifact Coordination
322
+
323
+ Large artifacts should be transferred out-of-band through runtime-owned storage.
324
+
325
+ Reserve request:
326
+
327
+ ```json
328
+ {
329
+ "type": "request",
330
+ "id": "req_artifact_1",
331
+ "method": "artifact.reserve",
332
+ "params": {
333
+ "run_id": "run_123",
334
+ "kind": "screenshot",
335
+ "mime_type": "image/png",
336
+ "metadata": {
337
+ "source": "computer.see"
338
+ }
339
+ }
340
+ }
341
+ ```
342
+
343
+ Reserve response:
344
+
345
+ ```json
346
+ {
347
+ "type": "response",
348
+ "id": "req_artifact_1",
349
+ "result": {
350
+ "artifact_id": "art_123",
351
+ "upload_url": "https://runtime.example/upload/art_123",
352
+ "headers": {
353
+ "Authorization": "Bearer upload-token"
354
+ }
355
+ }
356
+ }
357
+ ```
358
+
359
+ Complete request:
360
+
361
+ ```json
362
+ {
363
+ "type": "request",
364
+ "id": "req_artifact_2",
365
+ "method": "artifact.complete",
366
+ "params": {
367
+ "artifact_id": "art_123",
368
+ "size_bytes": 203456,
369
+ "sha256": "..."
370
+ }
371
+ }
372
+ ```
373
+
374
+ ## Versioning
375
+
376
+ The protocol string is `ya-environment-relay.v1`. Breaking changes should use `ya-environment-relay.v2`. Additive method fields can be negotiated through the `hello.capabilities` payload.
@@ -0,0 +1,216 @@
1
+ # 03. Relay Environment
2
+
3
+ ## Goal
4
+
5
+ Relay Environment maps `ya-environment-relay.v1` capabilities into `ya-agent-sdk` runtime abstractions. Agents and toolsets should interact with normal SDK interfaces while execution happens through a connected relay provider.
6
+
7
+ ## Environment Shape
8
+
9
+ ```python
10
+ class RelayEnvironment(Environment):
11
+ file_operator: RelayFileOperator
12
+ shell: RelayShell
13
+ resources: RelayResourceRegistry
14
+ toolsets: list[RelayToolset]
15
+ ```
16
+
17
+ The environment should be created from a binding:
18
+
19
+ ```python
20
+ class RelayEnvironmentBinding(BaseModel):
21
+ connection_id: str
22
+ client_id: str
23
+ roots: list[RelayRoot]
24
+ capabilities: list[str]
25
+ metadata: dict[str, Any] = Field(default_factory=dict)
26
+ ```
27
+
28
+ ## FileOperator Mapping
29
+
30
+ `RelayFileOperator` maps SDK file operations to `file.*` methods:
31
+
32
+ | SDK behavior | Relay method |
33
+ | ---------------- | ------------- |
34
+ | read text/bytes | `file.read` |
35
+ | write text/bytes | `file.write` |
36
+ | list directory | `file.list` |
37
+ | stat path | `file.stat` |
38
+ | create directory | `file.mkdir` |
39
+ | delete path | `file.delete` |
40
+ | search content | `file.search` |
41
+
42
+ Paths should be virtualized. The model and runtime see `/workspace/main/README.md`; the relay client maps it to an approved local root.
43
+
44
+ Request example:
45
+
46
+ ```json
47
+ {
48
+ "method": "file.read",
49
+ "params": {
50
+ "root_id": "main",
51
+ "path": "README.md",
52
+ "encoding": "utf-8"
53
+ }
54
+ }
55
+ ```
56
+
57
+ ## Shell Mapping
58
+
59
+ `RelayShell` maps SDK shell execution to `shell.*` methods:
60
+
61
+ | SDK behavior | Relay method |
62
+ | --------------- | -------------- |
63
+ | start command | `shell.start` |
64
+ | send stdin | `shell.input` |
65
+ | resize terminal | `shell.resize` |
66
+ | send signal | `shell.signal` |
67
+ | cancel command | `shell.cancel` |
68
+ | inspect command | `shell.status` |
69
+
70
+ Shell output uses stream frames:
71
+
72
+ ```json
73
+ {
74
+ "type": "stream",
75
+ "id": "req_shell_1",
76
+ "event": "stdout",
77
+ "data": "pytest started\n"
78
+ }
79
+ ```
80
+
81
+ The terminal response carries exit status:
82
+
83
+ ```json
84
+ {
85
+ "type": "response",
86
+ "id": "req_shell_1",
87
+ "result": {
88
+ "exit_code": 0,
89
+ "duration_ms": 18233
90
+ }
91
+ }
92
+ ```
93
+
94
+ ## Resource Mapping
95
+
96
+ Relay resources represent long-lived provider-side objects:
97
+
98
+ - browser sessions.
99
+ - computer sessions.
100
+ - database connections.
101
+ - local app automation handles.
102
+ - external service sessions.
103
+
104
+ Method mapping:
105
+
106
+ ```text
107
+ resource.list
108
+ resource.get
109
+ resource.create
110
+ resource.dispose
111
+ resource.export_state
112
+ resource.restore_state
113
+ ```
114
+
115
+ Resource state should integrate with SDK resumable resources when possible.
116
+
117
+ ## Tool Mapping
118
+
119
+ Relay custom tools are described by JSON Schema and exposed as SDK tools.
120
+
121
+ Tool descriptor:
122
+
123
+ ```json
124
+ {
125
+ "name": "local_open_in_editor",
126
+ "title": "Open File in Local Editor",
127
+ "description": "Open a workspace file in the user's configured editor.",
128
+ "input_schema": {
129
+ "type": "object",
130
+ "properties": {
131
+ "path": { "type": "string" },
132
+ "line": { "type": "integer" }
133
+ },
134
+ "required": ["path"]
135
+ },
136
+ "capability": "tools",
137
+ "risk": "low",
138
+ "approval_policy": "ask_once_per_run"
139
+ }
140
+ ```
141
+
142
+ Runtime mapping:
143
+
144
+ 1. Relay client registers tool descriptors.
145
+ 2. Runtime constructs a `RelayToolset` from accepted descriptors.
146
+ 3. Model calls generated SDK tool.
147
+ 4. Runtime sends `tool.call` over relay.
148
+ 5. Relay client executes the local tool.
149
+ 6. Runtime records trace and returns model-facing result.
150
+
151
+ ## Computer Mapping
152
+
153
+ Computer use can be represented as either:
154
+
155
+ - a specialized `RelayComputerProvider` used by a `ComputerUseToolset`.
156
+ - custom tools registered under the `tools` capability.
157
+
158
+ The specialized provider is preferred for product-grade computer use because it needs standard snapshot, action, artifact, pause, takeover, and policy semantics.
159
+
160
+ Method mapping:
161
+
162
+ ```text
163
+ computer.status
164
+ computer.see
165
+ computer.act
166
+ computer.pause
167
+ computer.resume
168
+ computer.takeover
169
+ computer.release
170
+ ```
171
+
172
+ ## Binding to Agent Runs
173
+
174
+ Each relay request should include runtime context when available:
175
+
176
+ ```json
177
+ {
178
+ "context": {
179
+ "session_id": "session_123",
180
+ "run_id": "run_456",
181
+ "tool_call_id": "call_789",
182
+ "workspace_id": "workspace_abc"
183
+ }
184
+ }
185
+ ```
186
+
187
+ This lets providers upload artifacts, render user-facing prompts, and attach local audit logs to runtime objects.
188
+
189
+ ## Lifecycle
190
+
191
+ ```mermaid
192
+ sequenceDiagram
193
+ participant Runtime as Runtime
194
+ participant Server as Relay Server
195
+ participant Client as Relay Client
196
+
197
+ Client->>Server: connect + hello
198
+ Server->>Runtime: provider registered
199
+ Runtime->>Server: create RelayEnvironment for session
200
+ Runtime->>Server: request file/shell/tool/computer
201
+ Server->>Client: relay request
202
+ Client-->>Server: response / stream
203
+ Server-->>Runtime: SDK result
204
+ Runtime->>Server: dispose run resources
205
+ ```
206
+
207
+ ## Reconnect
208
+
209
+ Relay clients can reconnect with the same `client_id`. Server behavior:
210
+
211
+ - mark capabilities unavailable when disconnected.
212
+ - fail pending requests with `relay_disconnected`.
213
+ - accept a fresh `hello` after reconnect.
214
+ - recreate environments against the new connection when session policy permits it.
215
+
216
+ Future protocol versions can add resumable request IDs and provider-side durable sessions.
@@ -0,0 +1,177 @@
1
+ # 04. Security and Policy
2
+
3
+ ## Goal
4
+
5
+ YA Environment Relay gives an agent runtime access to external execution environments. The protocol must make every capability explicit, scoped, revocable, and traceable.
6
+
7
+ ## Trust Layers
8
+
9
+ ```mermaid
10
+ flowchart TB
11
+ RuntimePolicy[Runtime Policy] --> RelayGrant[Relay Grant]
12
+ RelayGrant --> ProviderPolicy[Provider Local Policy]
13
+ ProviderPolicy --> Capability[Capability Execution]
14
+
15
+ RuntimePolicy --> HITL[Runtime HITL]
16
+ ProviderPolicy --> LocalPrompt[Provider User Prompt]
17
+ ProviderPolicy --> LocalBlock[Local Block]
18
+ ```
19
+
20
+ Runtime policy controls model-facing access. Provider policy controls local execution. Both can require approvals or block actions.
21
+
22
+ ## Authentication
23
+
24
+ Relay connections should authenticate with a scoped token:
25
+
26
+ ```http
27
+ Authorization: Bearer <relay-token>
28
+ ```
29
+
30
+ Token scope should include:
31
+
32
+ - client identity.
33
+ - allowed runtime or connection.
34
+ - workspace or Space identity.
35
+ - capability grants.
36
+ - expiration.
37
+ - revocation ID.
38
+
39
+ ## Authorization Grant
40
+
41
+ Grant shape:
42
+
43
+ ```ts
44
+ type RelayGrant = {
45
+ grant_id: string;
46
+ client_id: string;
47
+ runtime_id: string;
48
+ scope_id?: string;
49
+ capabilities: RelayCapabilityGrant[];
50
+ expires_at?: string;
51
+ created_at: string;
52
+ };
53
+
54
+ type RelayCapabilityGrant = {
55
+ capability: "fileops" | "shell" | "tools" | "resources" | "artifacts" | "computer";
56
+ enabled: boolean;
57
+ policy_id?: string;
58
+ roots?: RelayRootGrant[];
59
+ };
60
+ ```
61
+
62
+ File roots should be individually granted:
63
+
64
+ ```ts
65
+ type RelayRootGrant = {
66
+ root_id: string;
67
+ virtual_path: string;
68
+ mode: "ro" | "rw";
69
+ };
70
+ ```
71
+
72
+ ## Capability Acceptance
73
+
74
+ The relay server should accept only capabilities allowed by the active grant. The `hello` frame advertises provider capabilities. The server returns accepted capabilities in `relay.accepted`.
75
+
76
+ A provider may advertise `computer`; the server can accept only `fileops` and `tools` based on policy.
77
+
78
+ ## Path Safety
79
+
80
+ Relay file operations use virtual paths and root IDs. Providers must enforce root boundaries after path normalization.
81
+
82
+ Rules:
83
+
84
+ - normalize paths before access.
85
+ - resolve symlinks according to root policy.
86
+ - reject traversal outside roots.
87
+ - preserve read-only grants.
88
+ - include root ID and virtual path in audit logs.
89
+
90
+ ## Shell Safety
91
+
92
+ Shell grants should include:
93
+
94
+ - allowed roots and cwd.
95
+ - environment variable allowlist.
96
+ - network policy metadata.
97
+ - command approval policy.
98
+ - max runtime.
99
+ - streaming output limits.
100
+
101
+ Shell execution should use provider-local sandboxing when available.
102
+
103
+ ## Tool Safety
104
+
105
+ Custom tools should declare risk and approval policy:
106
+
107
+ ```ts
108
+ type RelayToolPolicy = {
109
+ risk: "low" | "medium" | "high" | "critical";
110
+ approval_policy: "allow" | "ask_once" | "ask_once_per_run" | "always_ask" | "block";
111
+ };
112
+ ```
113
+
114
+ Runtime profiles can override provider suggestions with stricter rules.
115
+
116
+ ## Computer Safety
117
+
118
+ Computer use should use additional local controls:
119
+
120
+ - explicit user enablement.
121
+ - visible active state.
122
+ - pause, takeover, release, stop.
123
+ - app allow/deny lists.
124
+ - screenshot retention policy.
125
+ - artifact upload policy.
126
+ - sensitive surface detection.
127
+
128
+ The provider should check local control state before each computer action.
129
+
130
+ ## Artifact Safety
131
+
132
+ Artifact uploads should be tied to a run or approved workspace scope.
133
+
134
+ Artifact policy dimensions:
135
+
136
+ - allowed MIME types.
137
+ - max size.
138
+ - retention days.
139
+ - redaction required.
140
+ - upload approval for sensitive classes.
141
+ - remote runtime upload consent.
142
+
143
+ ## Audit
144
+
145
+ Every relay request should be auditable:
146
+
147
+ ```ts
148
+ type RelayAuditEntry = {
149
+ id: string;
150
+ connection_id: string;
151
+ client_id: string;
152
+ method: string;
153
+ session_id?: string;
154
+ run_id?: string;
155
+ tool_call_id?: string;
156
+ capability: string;
157
+ policy_decision: "allowed" | "approved" | "blocked";
158
+ started_at: string;
159
+ completed_at?: string;
160
+ status: "succeeded" | "failed" | "cancelled";
161
+ };
162
+ ```
163
+
164
+ Runtime and provider can both keep audit logs. Runtime audit links to run trace. Provider audit supports local diagnostics and user trust review.
165
+
166
+ ## Revocation
167
+
168
+ Revocation should close active sockets and fail pending requests. Provider-side revocation should stop new execution immediately. Runtime-side revocation should remove the relay provider from capability discovery.
169
+
170
+ Common revocation triggers:
171
+
172
+ - user disables relay for a Space.
173
+ - token expires.
174
+ - provider loses required permissions.
175
+ - remote runtime identity changes.
176
+ - policy version changes.
177
+ - user emergency stop.
@@ -0,0 +1,129 @@
1
+ # 05. Implementation Plan
2
+
3
+ ## Phase 1: Spec and Models
4
+
5
+ Deliverables:
6
+
7
+ - spec folder.
8
+ - Python protocol models.
9
+ - TypeScript protocol model references for product clients.
10
+ - frame validation fixtures.
11
+ - method namespace constants.
12
+
13
+ Suggested Python package layout:
14
+
15
+ ```text
16
+ packages/ya-environment-relay/
17
+ pyproject.toml
18
+ ya_environment_relay/
19
+ __init__.py
20
+ protocol.py
21
+ errors.py
22
+ capabilities.py
23
+ ```
24
+
25
+ ## Phase 2: In-Process Mock Transport
26
+
27
+ Build an in-process transport before WebSocket integration.
28
+
29
+ Deliverables:
30
+
31
+ - mock relay server.
32
+ - mock relay client.
33
+ - request/response roundtrip.
34
+ - stream and cancel tests.
35
+ - fake fileops provider.
36
+ - fake custom tool provider.
37
+
38
+ This validates Environment mapping without product-specific networking.
39
+
40
+ ## Phase 3: SDK Environment Integration
41
+
42
+ Deliverables:
43
+
44
+ - `RelayEnvironment`.
45
+ - `RelayFileOperator`.
46
+ - `RelayShell`.
47
+ - `RelayToolset`.
48
+ - resource registry draft.
49
+
50
+ Tests:
51
+
52
+ - file read/list/write against fake provider.
53
+ - shell streaming result.
54
+ - generated tool call through `tool.call`.
55
+ - cancellation behavior.
56
+
57
+ ## Phase 4: WebSocket Transport
58
+
59
+ Deliverables:
60
+
61
+ - relay server transport.
62
+ - relay client transport.
63
+ - heartbeat.
64
+ - reconnect state.
65
+ - request timeout handling.
66
+ - connection registry.
67
+
68
+ The server transport can first live in Claw, then move common pieces into `ya-environment-relay` after the API stabilizes.
69
+
70
+ ## Phase 5: Claw Integration
71
+
72
+ Deliverables:
73
+
74
+ - Claw relay connection endpoint.
75
+ - relay provider registry.
76
+ - `RelayWorkspaceProvider`.
77
+ - session workspace binding support.
78
+ - run trace projections for relay calls.
79
+ - artifact reserve/upload/complete endpoints or adapters.
80
+
81
+ ## Phase 6: Desktop Integration
82
+
83
+ Deliverables:
84
+
85
+ - Desktop relay client.
86
+ - Space-level relay grants.
87
+ - local fileops provider.
88
+ - local shell provider.
89
+ - custom tool registration.
90
+ - relay diagnostics UI.
91
+
92
+ ## Phase 7: Computer Use Capability
93
+
94
+ Deliverables:
95
+
96
+ - `RelayComputerProvider`.
97
+ - `computer.status`.
98
+ - `computer.see`.
99
+ - `computer.act`.
100
+ - artifact upload for screenshots and UI trees.
101
+ - Desktop Host Computer Bridge integration.
102
+
103
+ ## Test Matrix
104
+
105
+ | Area | Test |
106
+ | ----------------- | ---------------------------------------------------- |
107
+ | protocol | frame parse/serialize fixtures |
108
+ | request lifecycle | success, error, timeout, cancel |
109
+ | streaming | stdout/stderr/progress ordering |
110
+ | fileops | path normalization and root boundary |
111
+ | shell | output stream and signal handling |
112
+ | tools | JSON Schema descriptor to SDK tool |
113
+ | artifacts | reserve/upload/complete failure modes |
114
+ | reconnect | pending request failure and provider re-registration |
115
+ | security | grant filtering and capability acceptance |
116
+
117
+ ## MVP Cut
118
+
119
+ Recommended first production slice:
120
+
121
+ 1. `ya-environment-relay.v1` protocol models.
122
+ 2. Claw WebSocket endpoint.
123
+ 3. Desktop relay client.
124
+ 4. file read/list/stat.
125
+ 5. shell start with stream and cancel.
126
+ 6. custom tool list/call.
127
+ 7. artifact reserve/complete.
128
+
129
+ Computer use becomes the first high-value specialized capability after the base relay environment is proven.
@@ -0,0 +1,56 @@
1
+ # YA Environment Relay Spec
2
+
3
+ YA Environment Relay is a provider-neutral protocol for connecting agent runtimes to external execution environments. It is designed to build on top of `ya-agent-sdk` Environment abstractions and expose remote or local capabilities as file operators, shells, resources, and toolsets.
4
+
5
+ YA Environment Relay is a general protocol. YA Desktop is one important relay client, but the protocol should also support headless relay agents, server-side workers, browser sandboxes, VM sandboxes, and custom tool hosts.
6
+
7
+ ## Goals
8
+
9
+ - Let an agent runtime call capabilities that live outside the runtime process.
10
+ - Represent remote capabilities as SDK Environment components.
11
+ - Support file operations, shell execution, custom tools, resources, artifacts, and computer use.
12
+ - Use one bidirectional transport for request/response, streaming, cancellation, and provider events.
13
+ - Keep tool schemas compatible with JSON Schema and model tool calling.
14
+ - Preserve runtime-owned tracing, approvals, and artifact persistence.
15
+
16
+ ## Package Direction
17
+
18
+ Initial work is spec-only. Future implementation can become a workspace package:
19
+
20
+ ```text
21
+ packages/ya-environment-relay/
22
+ spec/
23
+ pyproject.toml
24
+ ya_environment_relay/
25
+ protocol.py
26
+ client.py
27
+ server.py
28
+ environment.py
29
+ providers/
30
+ ```
31
+
32
+ The first Python implementation should integrate with `ya-agent-sdk` and expose:
33
+
34
+ - `RelayEnvironment`
35
+ - `RelayFileOperator`
36
+ - `RelayShell`
37
+ - `RelayToolset`
38
+ - `RelayResourceRegistry`
39
+ - protocol models for `ya-environment-relay.v1`
40
+
41
+ ## Section Map
42
+
43
+ | Section | Document | Topic |
44
+ | ------- | ------------------------------------------------------ | ---------------------------------------------------------------------- |
45
+ | 01 | [01-overview.md](01-overview.md) | goals, parties, capability model, relationship to SDK and Claw |
46
+ | 02 | [02-protocol.md](02-protocol.md) | WebSocket frames, request/response, streaming, cancellation, errors |
47
+ | 03 | [03-environment.md](03-environment.md) | SDK Environment mapping, file operator, shell, resources, custom tools |
48
+ | 04 | [04-security-and-policy.md](04-security-and-policy.md) | authentication, grants, policy, approvals, artifact safety |
49
+ | 05 | [05-implementation-plan.md](05-implementation-plan.md) | MVP phases and package layout |
50
+
51
+ ## Relationship to Products
52
+
53
+ - `ya-agent-sdk` provides the Environment concepts that YA Environment Relay implements remotely.
54
+ - `ya-claw` can host a relay server and route agent tool calls to connected providers.
55
+ - `ya-desktop` can act as a relay client for local files, shell, computer use, and custom tools.
56
+ - Future services can implement relay clients for sandboxes, browsers, VMs, and specialized tools.
@@ -0,0 +1,5 @@
1
+ """YA Environment Relay protocol package."""
2
+
3
+ PROTOCOL_VERSION = "ya-environment-relay.v1"
4
+
5
+ __all__ = ["PROTOCOL_VERSION"]