agent-relay 3.2.21 → 4.0.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 (157) hide show
  1. package/bin/agent-relay-broker-darwin-arm64 +0 -0
  2. package/bin/agent-relay-broker-darwin-x64 +0 -0
  3. package/bin/agent-relay-broker-linux-arm64 +0 -0
  4. package/bin/agent-relay-broker-linux-x64 +0 -0
  5. package/dist/index.cjs +5065 -1422
  6. package/dist/src/cli/bootstrap.d.ts.map +1 -1
  7. package/dist/src/cli/bootstrap.js +2 -0
  8. package/dist/src/cli/bootstrap.js.map +1 -1
  9. package/dist/src/cli/commands/agent-management.d.ts.map +1 -1
  10. package/dist/src/cli/commands/agent-management.js +14 -4
  11. package/dist/src/cli/commands/agent-management.js.map +1 -1
  12. package/dist/src/cli/commands/core.d.ts +2 -6
  13. package/dist/src/cli/commands/core.d.ts.map +1 -1
  14. package/dist/src/cli/commands/core.js +30 -12
  15. package/dist/src/cli/commands/core.js.map +1 -1
  16. package/dist/src/cli/commands/messaging.d.ts.map +1 -1
  17. package/dist/src/cli/commands/messaging.js +10 -3
  18. package/dist/src/cli/commands/messaging.js.map +1 -1
  19. package/dist/src/cli/commands/monitoring.d.ts +2 -2
  20. package/dist/src/cli/commands/monitoring.d.ts.map +1 -1
  21. package/dist/src/cli/commands/monitoring.js +15 -6
  22. package/dist/src/cli/commands/monitoring.js.map +1 -1
  23. package/dist/src/cli/commands/on/dotfiles.d.ts +35 -0
  24. package/dist/src/cli/commands/on/dotfiles.d.ts.map +1 -0
  25. package/dist/src/cli/commands/on/dotfiles.js +157 -0
  26. package/dist/src/cli/commands/on/dotfiles.js.map +1 -0
  27. package/dist/src/cli/commands/on/prereqs.d.ts +15 -0
  28. package/dist/src/cli/commands/on/prereqs.d.ts.map +1 -0
  29. package/dist/src/cli/commands/on/prereqs.js +103 -0
  30. package/dist/src/cli/commands/on/prereqs.js.map +1 -0
  31. package/dist/src/cli/commands/on/provision.d.ts +22 -0
  32. package/dist/src/cli/commands/on/provision.d.ts.map +1 -0
  33. package/dist/src/cli/commands/on/provision.js +157 -0
  34. package/dist/src/cli/commands/on/provision.js.map +1 -0
  35. package/dist/src/cli/commands/on/scan.d.ts +8 -0
  36. package/dist/src/cli/commands/on/scan.d.ts.map +1 -0
  37. package/dist/src/cli/commands/on/scan.js +59 -0
  38. package/dist/src/cli/commands/on/scan.js.map +1 -0
  39. package/dist/src/cli/commands/on/services.d.ts +17 -0
  40. package/dist/src/cli/commands/on/services.d.ts.map +1 -0
  41. package/dist/src/cli/commands/on/services.js +328 -0
  42. package/dist/src/cli/commands/on/services.js.map +1 -0
  43. package/dist/src/cli/commands/on/start.d.ts +61 -0
  44. package/dist/src/cli/commands/on/start.d.ts.map +1 -0
  45. package/dist/src/cli/commands/on/start.js +1071 -0
  46. package/dist/src/cli/commands/on/start.js.map +1 -0
  47. package/dist/src/cli/commands/on/stop.d.ts +4 -0
  48. package/dist/src/cli/commands/on/stop.d.ts.map +1 -0
  49. package/dist/src/cli/commands/on/stop.js +11 -0
  50. package/dist/src/cli/commands/on/stop.js.map +1 -0
  51. package/dist/src/cli/commands/on/token.d.ts +8 -0
  52. package/dist/src/cli/commands/on/token.d.ts.map +1 -0
  53. package/dist/src/cli/commands/on/token.js +26 -0
  54. package/dist/src/cli/commands/on/token.js.map +1 -0
  55. package/dist/src/cli/commands/on/workspace.d.ts +4 -0
  56. package/dist/src/cli/commands/on/workspace.d.ts.map +1 -0
  57. package/dist/src/cli/commands/on/workspace.js +241 -0
  58. package/dist/src/cli/commands/on/workspace.js.map +1 -0
  59. package/dist/src/cli/commands/on.d.ts +10 -0
  60. package/dist/src/cli/commands/on.d.ts.map +1 -0
  61. package/dist/src/cli/commands/on.js +52 -0
  62. package/dist/src/cli/commands/on.js.map +1 -0
  63. package/dist/src/cli/commands/setup.d.ts.map +1 -1
  64. package/dist/src/cli/commands/setup.js +10 -21
  65. package/dist/src/cli/commands/setup.js.map +1 -1
  66. package/dist/src/cli/lib/bridge.js +1 -1
  67. package/dist/src/cli/lib/bridge.js.map +1 -1
  68. package/dist/src/cli/lib/broker-lifecycle.d.ts +14 -4
  69. package/dist/src/cli/lib/broker-lifecycle.d.ts.map +1 -1
  70. package/dist/src/cli/lib/broker-lifecycle.js +82 -120
  71. package/dist/src/cli/lib/broker-lifecycle.js.map +1 -1
  72. package/dist/src/cli/lib/client-factory.d.ts +2 -2
  73. package/dist/src/cli/lib/client-factory.d.ts.map +1 -1
  74. package/dist/src/cli/lib/client-factory.js +14 -11
  75. package/dist/src/cli/lib/client-factory.js.map +1 -1
  76. package/dist/src/cli/lib/core-maintenance.d.ts.map +1 -1
  77. package/dist/src/cli/lib/core-maintenance.js +11 -22
  78. package/dist/src/cli/lib/core-maintenance.js.map +1 -1
  79. package/package.json +14 -11
  80. package/packages/acp-bridge/package.json +2 -2
  81. package/packages/brand/package.json +1 -1
  82. package/packages/cloud/package.json +2 -2
  83. package/packages/config/package.json +1 -1
  84. package/packages/hooks/package.json +4 -4
  85. package/packages/memory/package.json +2 -2
  86. package/packages/openclaw/package.json +2 -2
  87. package/packages/policy/package.json +2 -2
  88. package/packages/sdk/README.md +10 -3
  89. package/packages/sdk/dist/client.d.ts +108 -196
  90. package/packages/sdk/dist/client.d.ts.map +1 -1
  91. package/packages/sdk/dist/client.js +336 -824
  92. package/packages/sdk/dist/client.js.map +1 -1
  93. package/packages/sdk/dist/examples/example.js +2 -5
  94. package/packages/sdk/dist/examples/example.js.map +1 -1
  95. package/packages/sdk/dist/index.d.ts +3 -1
  96. package/packages/sdk/dist/index.d.ts.map +1 -1
  97. package/packages/sdk/dist/index.js +3 -1
  98. package/packages/sdk/dist/index.js.map +1 -1
  99. package/packages/sdk/dist/relay-adapter.d.ts +9 -26
  100. package/packages/sdk/dist/relay-adapter.d.ts.map +1 -1
  101. package/packages/sdk/dist/relay-adapter.js +75 -47
  102. package/packages/sdk/dist/relay-adapter.js.map +1 -1
  103. package/packages/sdk/dist/relay.d.ts +24 -5
  104. package/packages/sdk/dist/relay.d.ts.map +1 -1
  105. package/packages/sdk/dist/relay.js +213 -43
  106. package/packages/sdk/dist/relay.js.map +1 -1
  107. package/packages/sdk/dist/transport.d.ts +58 -0
  108. package/packages/sdk/dist/transport.d.ts.map +1 -0
  109. package/packages/sdk/dist/transport.js +184 -0
  110. package/packages/sdk/dist/transport.js.map +1 -0
  111. package/packages/sdk/dist/types.d.ts +69 -0
  112. package/packages/sdk/dist/types.d.ts.map +1 -0
  113. package/packages/sdk/dist/types.js +5 -0
  114. package/packages/sdk/dist/types.js.map +1 -0
  115. package/packages/sdk/dist/workflows/cli.js +46 -2
  116. package/packages/sdk/dist/workflows/cli.js.map +1 -1
  117. package/packages/sdk/dist/workflows/file-db.d.ts +2 -0
  118. package/packages/sdk/dist/workflows/file-db.d.ts.map +1 -1
  119. package/packages/sdk/dist/workflows/file-db.js +20 -3
  120. package/packages/sdk/dist/workflows/file-db.js.map +1 -1
  121. package/packages/sdk/dist/workflows/runner.d.ts +6 -1
  122. package/packages/sdk/dist/workflows/runner.d.ts.map +1 -1
  123. package/packages/sdk/dist/workflows/runner.js +157 -11
  124. package/packages/sdk/dist/workflows/runner.js.map +1 -1
  125. package/packages/sdk/dist/workflows/validator.d.ts.map +1 -1
  126. package/packages/sdk/dist/workflows/validator.js +17 -2
  127. package/packages/sdk/dist/workflows/validator.js.map +1 -1
  128. package/packages/sdk/package.json +2 -2
  129. package/packages/sdk/src/__tests__/resume-fallback.test.ts +415 -0
  130. package/packages/sdk/src/__tests__/unit.test.ts +100 -1
  131. package/packages/sdk/src/client.ts +422 -1072
  132. package/packages/sdk/src/examples/example.ts +2 -5
  133. package/packages/sdk/src/index.ts +8 -1
  134. package/packages/sdk/src/relay-adapter.ts +75 -55
  135. package/packages/sdk/src/relay.ts +260 -57
  136. package/packages/sdk/src/transport.ts +216 -0
  137. package/packages/sdk/src/types.ts +75 -0
  138. package/packages/sdk/src/workflows/cli.ts +53 -2
  139. package/packages/sdk/src/workflows/file-db.ts +22 -3
  140. package/packages/sdk/src/workflows/runner.ts +178 -11
  141. package/packages/sdk/src/workflows/validator.ts +20 -2
  142. package/packages/sdk-py/pyproject.toml +1 -1
  143. package/packages/sdk-py/src/agent_relay/__init__.py +0 -8
  144. package/packages/sdk-py/src/agent_relay/client.py +329 -522
  145. package/packages/sdk-py/src/agent_relay/protocol.py +2 -96
  146. package/packages/sdk-py/src/agent_relay/relay.py +1 -4
  147. package/packages/sdk-py/tests/test_wait_for_api_url.py +92 -0
  148. package/packages/sdk-py/uv.lock +5388 -0
  149. package/packages/telemetry/dist/client.d.ts.map +1 -1
  150. package/packages/telemetry/dist/client.js +1 -1
  151. package/packages/telemetry/dist/client.js.map +1 -1
  152. package/packages/telemetry/package.json +1 -1
  153. package/packages/telemetry/src/client.ts +3 -10
  154. package/packages/trajectory/package.json +2 -2
  155. package/packages/user-directory/package.json +2 -2
  156. package/packages/utils/package.json +2 -2
  157. package/scripts/postinstall.js +121 -1
@@ -1,110 +1,16 @@
1
- """Wire protocol types for the Agent Relay broker communication.
1
+ """Wire protocol types for the Agent Relay broker.
2
2
 
3
3
  Matches the TypeScript definitions in packages/sdk/src/protocol.ts.
4
4
  """
5
5
 
6
6
  from __future__ import annotations
7
7
 
8
- from dataclasses import dataclass, field
9
- from typing import Any, Literal, Optional
10
-
11
- PROTOCOL_VERSION = 1
8
+ from typing import Any, Literal
12
9
 
13
10
  AgentRuntime = Literal["pty", "headless"]
14
11
  HeadlessProvider = Literal["claude", "opencode"]
15
12
  MessageInjectionMode = Literal["wait", "steer"]
16
13
 
17
-
18
- @dataclass
19
- class RestartPolicy:
20
- enabled: bool = False
21
- max_restarts: int = 3
22
- cooldown_ms: int = 1000
23
- max_consecutive_failures: int = 3
24
-
25
- def to_dict(self) -> dict[str, Any]:
26
- return {
27
- "enabled": self.enabled,
28
- "max_restarts": self.max_restarts,
29
- "cooldown_ms": self.cooldown_ms,
30
- "max_consecutive_failures": self.max_consecutive_failures,
31
- }
32
-
33
-
34
- @dataclass
35
- class AgentSpec:
36
- """Specification for spawning an agent."""
37
-
38
- name: str
39
- runtime: AgentRuntime = "pty"
40
- provider: Optional[HeadlessProvider] = None
41
- cli: Optional[str] = None
42
- args: list[str] = field(default_factory=list)
43
- channels: list[str] = field(default_factory=list)
44
- model: Optional[str] = None
45
- cwd: Optional[str] = None
46
- team: Optional[str] = None
47
- shadow_of: Optional[str] = None
48
- shadow_mode: Optional[str] = None
49
- restart_policy: Optional[RestartPolicy] = None
50
-
51
- def to_dict(self) -> dict[str, Any]:
52
- d: dict[str, Any] = {
53
- "name": self.name,
54
- "runtime": self.runtime,
55
- }
56
- if self.provider is not None:
57
- d["provider"] = self.provider
58
- if self.cli is not None:
59
- d["cli"] = self.cli
60
- if self.args:
61
- d["args"] = self.args
62
- if self.channels:
63
- d["channels"] = self.channels
64
- if self.model is not None:
65
- d["model"] = self.model
66
- if self.cwd is not None:
67
- d["cwd"] = self.cwd
68
- if self.team is not None:
69
- d["team"] = self.team
70
- if self.shadow_of is not None:
71
- d["shadow_of"] = self.shadow_of
72
- if self.shadow_mode is not None:
73
- d["shadow_mode"] = self.shadow_mode
74
- if self.restart_policy is not None:
75
- d["restart_policy"] = self.restart_policy.to_dict()
76
- return d
77
-
78
-
79
- @dataclass
80
- class ProtocolEnvelope:
81
- """JSON envelope for all broker communication."""
82
-
83
- v: int
84
- type: str
85
- payload: dict[str, Any]
86
- request_id: Optional[str] = None
87
-
88
- def to_dict(self) -> dict[str, Any]:
89
- d: dict[str, Any] = {
90
- "v": self.v,
91
- "type": self.type,
92
- "payload": self.payload,
93
- }
94
- if self.request_id is not None:
95
- d["request_id"] = self.request_id
96
- return d
97
-
98
- @classmethod
99
- def from_dict(cls, data: dict[str, Any]) -> ProtocolEnvelope:
100
- return cls(
101
- v=data.get("v", 0),
102
- type=data.get("type", ""),
103
- payload=data.get("payload", {}),
104
- request_id=data.get("request_id"),
105
- )
106
-
107
-
108
14
  # BrokerEvent is a dict with a 'kind' field discriminator.
109
15
  # Event kinds: agent_spawned, agent_released, agent_exit, agent_exited,
110
16
  # relay_inbound, worker_stream, worker_ready, worker_error,
@@ -424,8 +424,6 @@ class AgentRelay:
424
424
  "channels": self._default_channels,
425
425
  "cwd": cwd,
426
426
  "env": env,
427
- "request_timeout_ms": request_timeout_ms,
428
- "shutdown_timeout_ms": shutdown_timeout_ms,
429
427
  }
430
428
 
431
429
  self._client: Optional[AgentRelayClient] = None
@@ -477,8 +475,7 @@ class AgentRelay:
477
475
 
478
476
  # Remove None values to use defaults
479
477
  kwargs = {k: v for k, v in self._client_kwargs.items() if v is not None}
480
- client = AgentRelayClient(**kwargs)
481
- await client.start_client()
478
+ client = await AgentRelayClient.spawn(**kwargs)
482
479
 
483
480
  self._client = client
484
481
  if client.workspace_key:
@@ -0,0 +1,92 @@
1
+ """Tests for _wait_for_api_url."""
2
+
3
+ import asyncio
4
+ from unittest.mock import AsyncMock, PropertyMock
5
+
6
+ import pytest
7
+
8
+ from agent_relay.client import AgentRelayProcessError, _wait_for_api_url
9
+
10
+
11
+ def _make_process(lines: list[str], returncode: int | None = 0):
12
+ """Create a mock asyncio.subprocess.Process with canned stdout lines."""
13
+ remaining = list(lines)
14
+
15
+ async def readline() -> bytes:
16
+ if remaining:
17
+ return (remaining.pop(0) + "\n").encode("utf-8")
18
+ return b""
19
+
20
+ process = AsyncMock()
21
+ process.stdout = AsyncMock()
22
+ process.stdout.readline = readline
23
+ type(process).returncode = PropertyMock(return_value=returncode)
24
+ return process
25
+
26
+
27
+ class TestWaitForApiUrl:
28
+ async def test_parses_default_loopback(self):
29
+ process = _make_process([
30
+ "[agent-relay] API listening on http://127.0.0.1:3889",
31
+ ])
32
+ url = await _wait_for_api_url(process, 5000)
33
+ assert url == "http://127.0.0.1:3889"
34
+
35
+ async def test_parses_wildcard_bind(self):
36
+ process = _make_process([
37
+ "[agent-relay] API listening on http://0.0.0.0:4000",
38
+ ])
39
+ url = await _wait_for_api_url(process, 5000)
40
+ assert url == "http://0.0.0.0:4000"
41
+
42
+ async def test_parses_custom_ip(self):
43
+ process = _make_process([
44
+ "[agent-relay] API listening on http://10.0.1.5:8080",
45
+ ])
46
+ url = await _wait_for_api_url(process, 5000)
47
+ assert url == "http://10.0.1.5:8080"
48
+
49
+ async def test_parses_https(self):
50
+ process = _make_process([
51
+ "[agent-relay] API listening on https://broker.example.com:443",
52
+ ])
53
+ url = await _wait_for_api_url(process, 5000)
54
+ assert url == "https://broker.example.com:443"
55
+
56
+ async def test_skips_non_matching_lines(self):
57
+ process = _make_process([
58
+ "[agent-relay] Starting broker...",
59
+ "[agent-relay] Loading config",
60
+ "[agent-relay] API listening on http://127.0.0.1:5555",
61
+ ])
62
+ url = await _wait_for_api_url(process, 5000)
63
+ assert url == "http://127.0.0.1:5555"
64
+
65
+ async def test_raises_on_process_exit_before_ready(self):
66
+ process = _make_process(
67
+ ["[agent-relay] Starting broker..."],
68
+ returncode=1,
69
+ )
70
+ with pytest.raises(AgentRelayProcessError, match="exited with code 1"):
71
+ await _wait_for_api_url(process, 5000)
72
+
73
+ async def test_raises_on_timeout(self):
74
+ async def slow_readline() -> bytes:
75
+ await asyncio.sleep(10)
76
+ return b""
77
+
78
+ process = AsyncMock()
79
+ process.stdout = AsyncMock()
80
+ process.stdout.readline = slow_readline
81
+ type(process).returncode = PropertyMock(return_value=None)
82
+
83
+ with pytest.raises(AgentRelayProcessError, match="did not report API URL"):
84
+ await _wait_for_api_url(process, 50)
85
+
86
+ async def test_ignores_lines_with_colon_but_no_url(self):
87
+ process = _make_process([
88
+ "[agent-relay] config: loaded from /etc/relay.conf",
89
+ "[agent-relay] API listening on http://127.0.0.1:9999",
90
+ ])
91
+ url = await _wait_for_api_url(process, 5000)
92
+ assert url == "http://127.0.0.1:9999"