agent-relay 3.2.2 → 3.2.4

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 (246) 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 +1358 -941
  6. package/dist/src/cli/commands/agent-management.d.ts +2 -2
  7. package/dist/src/cli/commands/agent-management.d.ts.map +1 -1
  8. package/dist/src/cli/commands/agent-management.js +41 -240
  9. package/dist/src/cli/commands/agent-management.js.map +1 -1
  10. package/dist/src/cli/commands/messaging.d.ts +1 -1
  11. package/dist/src/cli/commands/messaging.d.ts.map +1 -1
  12. package/dist/src/cli/commands/messaging.js +14 -5
  13. package/dist/src/cli/commands/messaging.js.map +1 -1
  14. package/dist/src/cli/lib/agent-management-listing.d.ts +4 -1
  15. package/dist/src/cli/lib/agent-management-listing.d.ts.map +1 -1
  16. package/dist/src/cli/lib/agent-management-listing.js +27 -2
  17. package/dist/src/cli/lib/agent-management-listing.js.map +1 -1
  18. package/package.json +11 -10
  19. package/packages/acp-bridge/package.json +2 -2
  20. package/packages/config/package.json +1 -1
  21. package/packages/hooks/package.json +4 -4
  22. package/packages/memory/package.json +2 -2
  23. package/packages/openclaw/package.json +2 -2
  24. package/packages/policy/package.json +2 -2
  25. package/packages/sdk/ADAPTER_REVIEW.md +109 -0
  26. package/packages/sdk/dist/client.d.ts +66 -0
  27. package/packages/sdk/dist/client.d.ts.map +1 -1
  28. package/packages/sdk/dist/client.js +230 -0
  29. package/packages/sdk/dist/client.js.map +1 -1
  30. package/packages/sdk/dist/communicate/a2a-bridge.d.ts +25 -0
  31. package/packages/sdk/dist/communicate/a2a-bridge.d.ts.map +1 -0
  32. package/packages/sdk/dist/communicate/a2a-bridge.js +89 -0
  33. package/packages/sdk/dist/communicate/a2a-bridge.js.map +1 -0
  34. package/packages/sdk/dist/communicate/a2a-server.d.ts +31 -0
  35. package/packages/sdk/dist/communicate/a2a-server.d.ts.map +1 -0
  36. package/packages/sdk/dist/communicate/a2a-server.js +220 -0
  37. package/packages/sdk/dist/communicate/a2a-server.js.map +1 -0
  38. package/packages/sdk/dist/communicate/a2a-transport.d.ts +48 -0
  39. package/packages/sdk/dist/communicate/a2a-transport.d.ts.map +1 -0
  40. package/packages/sdk/dist/communicate/a2a-transport.js +302 -0
  41. package/packages/sdk/dist/communicate/a2a-transport.js.map +1 -0
  42. package/packages/sdk/dist/communicate/a2a-types.d.ts +107 -0
  43. package/packages/sdk/dist/communicate/a2a-types.d.ts.map +1 -0
  44. package/packages/sdk/dist/communicate/a2a-types.js +209 -0
  45. package/packages/sdk/dist/communicate/a2a-types.js.map +1 -0
  46. package/packages/sdk/dist/communicate/adapters/claude-sdk.d.ts +28 -0
  47. package/packages/sdk/dist/communicate/adapters/claude-sdk.d.ts.map +1 -0
  48. package/packages/sdk/dist/communicate/adapters/claude-sdk.js +47 -0
  49. package/packages/sdk/dist/communicate/adapters/claude-sdk.js.map +1 -0
  50. package/packages/sdk/dist/communicate/adapters/crewai.d.ts +42 -0
  51. package/packages/sdk/dist/communicate/adapters/crewai.d.ts.map +1 -0
  52. package/packages/sdk/dist/communicate/adapters/crewai.js +95 -0
  53. package/packages/sdk/dist/communicate/adapters/crewai.js.map +1 -0
  54. package/packages/sdk/dist/communicate/adapters/google-adk.d.ts +53 -0
  55. package/packages/sdk/dist/communicate/adapters/google-adk.d.ts.map +1 -0
  56. package/packages/sdk/dist/communicate/adapters/google-adk.js +77 -0
  57. package/packages/sdk/dist/communicate/adapters/google-adk.js.map +1 -0
  58. package/packages/sdk/dist/communicate/adapters/index.d.ts +7 -0
  59. package/packages/sdk/dist/communicate/adapters/index.d.ts.map +1 -0
  60. package/packages/sdk/dist/communicate/adapters/index.js +7 -0
  61. package/packages/sdk/dist/communicate/adapters/index.js.map +1 -0
  62. package/packages/sdk/dist/communicate/adapters/langgraph.d.ts +40 -0
  63. package/packages/sdk/dist/communicate/adapters/langgraph.d.ts.map +1 -0
  64. package/packages/sdk/dist/communicate/adapters/langgraph.js +77 -0
  65. package/packages/sdk/dist/communicate/adapters/langgraph.js.map +1 -0
  66. package/packages/sdk/dist/communicate/adapters/openai-agents.d.ts +25 -0
  67. package/packages/sdk/dist/communicate/adapters/openai-agents.d.ts.map +1 -0
  68. package/packages/sdk/dist/communicate/adapters/openai-agents.js +70 -0
  69. package/packages/sdk/dist/communicate/adapters/openai-agents.js.map +1 -0
  70. package/packages/sdk/dist/communicate/adapters/pi.d.ts +45 -0
  71. package/packages/sdk/dist/communicate/adapters/pi.d.ts.map +1 -0
  72. package/packages/sdk/dist/communicate/adapters/pi.js +59 -0
  73. package/packages/sdk/dist/communicate/adapters/pi.js.map +1 -0
  74. package/packages/sdk/dist/communicate/core.d.ts +58 -0
  75. package/packages/sdk/dist/communicate/core.d.ts.map +1 -0
  76. package/packages/sdk/dist/communicate/core.js +128 -0
  77. package/packages/sdk/dist/communicate/core.js.map +1 -0
  78. package/packages/sdk/dist/communicate/index.d.ts +4 -0
  79. package/packages/sdk/dist/communicate/index.d.ts.map +1 -0
  80. package/packages/sdk/dist/communicate/index.js +4 -0
  81. package/packages/sdk/dist/communicate/index.js.map +1 -0
  82. package/packages/sdk/dist/communicate/transport.d.ts +36 -0
  83. package/packages/sdk/dist/communicate/transport.d.ts.map +1 -0
  84. package/packages/sdk/dist/communicate/transport.js +371 -0
  85. package/packages/sdk/dist/communicate/transport.js.map +1 -0
  86. package/packages/sdk/dist/communicate/types.d.ts +58 -0
  87. package/packages/sdk/dist/communicate/types.d.ts.map +1 -0
  88. package/packages/sdk/dist/communicate/types.js +66 -0
  89. package/packages/sdk/dist/communicate/types.js.map +1 -0
  90. package/packages/sdk/dist/workflows/builder.d.ts +35 -5
  91. package/packages/sdk/dist/workflows/builder.d.ts.map +1 -1
  92. package/packages/sdk/dist/workflows/builder.js +81 -7
  93. package/packages/sdk/dist/workflows/builder.js.map +1 -1
  94. package/packages/sdk/dist/workflows/cli.js +14 -1
  95. package/packages/sdk/dist/workflows/cli.js.map +1 -1
  96. package/packages/sdk/dist/workflows/runner.d.ts +10 -2
  97. package/packages/sdk/dist/workflows/runner.d.ts.map +1 -1
  98. package/packages/sdk/dist/workflows/runner.js +95 -1
  99. package/packages/sdk/dist/workflows/runner.js.map +1 -1
  100. package/packages/sdk/dist/workflows/types.d.ts +11 -0
  101. package/packages/sdk/dist/workflows/types.d.ts.map +1 -1
  102. package/packages/sdk/examples/communicate/claude_sdk_example.ts +5 -0
  103. package/packages/sdk/examples/communicate/pi_example.ts +8 -0
  104. package/packages/sdk/package.json +48 -2
  105. package/packages/sdk/src/__tests__/builder-deterministic.test.ts +132 -0
  106. package/packages/sdk/src/__tests__/communicate/a2a-bridge.test.ts +211 -0
  107. package/packages/sdk/src/__tests__/communicate/a2a-server.test.ts +359 -0
  108. package/packages/sdk/src/__tests__/communicate/a2a-transport.test.ts +537 -0
  109. package/packages/sdk/src/__tests__/communicate/a2a-types.test.ts +297 -0
  110. package/packages/sdk/src/__tests__/communicate/adapters/claude-sdk.test.ts +163 -0
  111. package/packages/sdk/src/__tests__/communicate/adapters/crewai.test.ts +219 -0
  112. package/packages/sdk/src/__tests__/communicate/adapters/e2e-crewai.test.ts +101 -0
  113. package/packages/sdk/src/__tests__/communicate/adapters/e2e-google-adk.test.ts +166 -0
  114. package/packages/sdk/src/__tests__/communicate/adapters/e2e-langgraph.test.ts +181 -0
  115. package/packages/sdk/src/__tests__/communicate/adapters/e2e-openai-agents.test.ts +137 -0
  116. package/packages/sdk/src/__tests__/communicate/adapters/e2e-pi.test.ts +140 -0
  117. package/packages/sdk/src/__tests__/communicate/adapters/google-adk.test.ts +200 -0
  118. package/packages/sdk/src/__tests__/communicate/adapters/langgraph.test.ts +162 -0
  119. package/packages/sdk/src/__tests__/communicate/adapters/openai-agents.test.ts +166 -0
  120. package/packages/sdk/src/__tests__/communicate/adapters/pi.test.ts +140 -0
  121. package/packages/sdk/src/__tests__/communicate/core.test.ts +574 -0
  122. package/packages/sdk/src/__tests__/communicate/integration/cross-framework.test.ts +353 -0
  123. package/packages/sdk/src/__tests__/communicate/transport.test.ts +613 -0
  124. package/packages/sdk/src/__tests__/start-from.test.ts +346 -0
  125. package/packages/sdk/src/client.ts +301 -0
  126. package/packages/sdk/src/communicate/a2a-bridge.ts +111 -0
  127. package/packages/sdk/src/communicate/a2a-server.ts +277 -0
  128. package/packages/sdk/src/communicate/a2a-transport.ts +395 -0
  129. package/packages/sdk/src/communicate/a2a-types.ts +338 -0
  130. package/packages/sdk/src/communicate/adapters/claude-sdk.ts +85 -0
  131. package/packages/sdk/src/communicate/adapters/crewai.ts +141 -0
  132. package/packages/sdk/src/communicate/adapters/google-adk.ts +139 -0
  133. package/packages/sdk/src/communicate/adapters/index.ts +6 -0
  134. package/packages/sdk/src/communicate/adapters/langgraph.ts +112 -0
  135. package/packages/sdk/src/communicate/adapters/openai-agents.ts +113 -0
  136. package/packages/sdk/src/communicate/adapters/pi.ts +105 -0
  137. package/packages/sdk/src/communicate/core.ts +157 -0
  138. package/packages/sdk/src/communicate/index.ts +3 -0
  139. package/packages/sdk/src/communicate/transport.ts +489 -0
  140. package/packages/sdk/src/communicate/types.ts +106 -0
  141. package/packages/sdk/src/examples/workflows/fix-dashboard-user-registration.yaml +182 -0
  142. package/packages/sdk/src/workflows/builder.ts +97 -9
  143. package/packages/sdk/src/workflows/cli.ts +16 -1
  144. package/packages/sdk/src/workflows/runner.ts +110 -1
  145. package/packages/sdk/src/workflows/types.ts +14 -0
  146. package/packages/sdk/tsconfig.build.json +1 -7
  147. package/packages/sdk/tsconfig.json +1 -7
  148. package/packages/sdk-py/README.md +67 -25
  149. package/packages/sdk-py/examples/communicate/agno_example.py +8 -0
  150. package/packages/sdk-py/examples/communicate/claude_sdk_example.py +6 -0
  151. package/packages/sdk-py/examples/communicate/crewai_example.py +7 -0
  152. package/packages/sdk-py/examples/communicate/google_adk_example.py +7 -0
  153. package/packages/sdk-py/examples/communicate/openai_agents_example.py +8 -0
  154. package/packages/sdk-py/examples/communicate/swarms_example.py +7 -0
  155. package/packages/sdk-py/pyproject.toml +12 -1
  156. package/packages/sdk-py/src/agent_relay/__init__.py +8 -0
  157. package/packages/sdk-py/src/agent_relay/builder.py +65 -26
  158. package/packages/sdk-py/src/agent_relay/communicate/__init__.py +6 -0
  159. package/packages/sdk-py/src/agent_relay/communicate/a2a_bridge.py +138 -0
  160. package/packages/sdk-py/src/agent_relay/communicate/a2a_server.py +242 -0
  161. package/packages/sdk-py/src/agent_relay/communicate/a2a_transport.py +366 -0
  162. package/packages/sdk-py/src/agent_relay/communicate/a2a_types.py +294 -0
  163. package/packages/sdk-py/src/agent_relay/communicate/adapters/__init__.py +10 -0
  164. package/packages/sdk-py/src/agent_relay/communicate/adapters/agno.py +74 -0
  165. package/packages/sdk-py/src/agent_relay/communicate/adapters/claude_sdk.py +78 -0
  166. package/packages/sdk-py/src/agent_relay/communicate/adapters/crewai.py +143 -0
  167. package/packages/sdk-py/src/agent_relay/communicate/adapters/google_adk.py +69 -0
  168. package/packages/sdk-py/src/agent_relay/communicate/adapters/openai_agents.py +86 -0
  169. package/packages/sdk-py/src/agent_relay/communicate/adapters/pi.py +175 -0
  170. package/packages/sdk-py/src/agent_relay/communicate/adapters/swarms.py +44 -0
  171. package/packages/sdk-py/src/agent_relay/communicate/core.py +293 -0
  172. package/packages/sdk-py/src/agent_relay/communicate/transport.py +502 -0
  173. package/packages/sdk-py/src/agent_relay/communicate/types.py +89 -0
  174. package/packages/sdk-py/src/agent_relay/types.py +2 -1
  175. package/packages/sdk-py/tests/communicate/__init__.py +0 -0
  176. package/packages/sdk-py/tests/communicate/adapters/__init__.py +0 -0
  177. package/packages/sdk-py/tests/communicate/adapters/e2e_test_agno.py +154 -0
  178. package/packages/sdk-py/tests/communicate/adapters/e2e_test_claude_sdk.py +428 -0
  179. package/packages/sdk-py/tests/communicate/adapters/e2e_test_crewai.py +234 -0
  180. package/packages/sdk-py/tests/communicate/adapters/e2e_test_google_adk.py +182 -0
  181. package/packages/sdk-py/tests/communicate/adapters/e2e_test_langgraph.py +262 -0
  182. package/packages/sdk-py/tests/communicate/adapters/e2e_test_openai_agents.py +88 -0
  183. package/packages/sdk-py/tests/communicate/adapters/e2e_test_pi.py +156 -0
  184. package/packages/sdk-py/tests/communicate/adapters/e2e_test_swarms.py +239 -0
  185. package/packages/sdk-py/tests/communicate/adapters/test_agno.py +140 -0
  186. package/packages/sdk-py/tests/communicate/adapters/test_claude_sdk.py +147 -0
  187. package/packages/sdk-py/tests/communicate/adapters/test_crewai.py +136 -0
  188. package/packages/sdk-py/tests/communicate/adapters/test_google_adk.py +125 -0
  189. package/packages/sdk-py/tests/communicate/adapters/test_openai_agents.py +99 -0
  190. package/packages/sdk-py/tests/communicate/adapters/test_pi.py +270 -0
  191. package/packages/sdk-py/tests/communicate/adapters/test_swarms.py +113 -0
  192. package/packages/sdk-py/tests/communicate/conftest.py +555 -0
  193. package/packages/sdk-py/tests/communicate/integration/__init__.py +1 -0
  194. package/packages/sdk-py/tests/communicate/integration/test_cross_framework.py +331 -0
  195. package/packages/sdk-py/tests/communicate/integration/test_end_to_end.py +151 -0
  196. package/packages/sdk-py/tests/communicate/test_a2a_bridge.py +363 -0
  197. package/packages/sdk-py/tests/communicate/test_a2a_server.py +346 -0
  198. package/packages/sdk-py/tests/communicate/test_a2a_transport.py +561 -0
  199. package/packages/sdk-py/tests/communicate/test_a2a_types.py +342 -0
  200. package/packages/sdk-py/tests/communicate/test_auto_detect.py +67 -0
  201. package/packages/sdk-py/tests/communicate/test_core.py +331 -0
  202. package/packages/sdk-py/tests/communicate/test_transport.py +373 -0
  203. package/packages/sdk-py/tests/communicate/test_types.py +285 -0
  204. package/packages/sdk-py/tests/test_builder_deterministic.py +118 -0
  205. package/packages/telemetry/package.json +1 -1
  206. package/packages/trajectory/package.json +2 -2
  207. package/packages/user-directory/package.json +2 -2
  208. package/packages/utils/package.json +2 -2
  209. package/packages/sdk/dist/__tests__/completion-pipeline.test.d.ts +0 -14
  210. package/packages/sdk/dist/__tests__/completion-pipeline.test.d.ts.map +0 -1
  211. package/packages/sdk/dist/__tests__/completion-pipeline.test.js +0 -1476
  212. package/packages/sdk/dist/__tests__/completion-pipeline.test.js.map +0 -1
  213. package/packages/sdk/dist/__tests__/contract-fixtures.test.d.ts +0 -2
  214. package/packages/sdk/dist/__tests__/contract-fixtures.test.d.ts.map +0 -1
  215. package/packages/sdk/dist/__tests__/contract-fixtures.test.js +0 -152
  216. package/packages/sdk/dist/__tests__/contract-fixtures.test.js.map +0 -1
  217. package/packages/sdk/dist/__tests__/e2e-owner-review.test.d.ts +0 -16
  218. package/packages/sdk/dist/__tests__/e2e-owner-review.test.d.ts.map +0 -1
  219. package/packages/sdk/dist/__tests__/e2e-owner-review.test.js +0 -640
  220. package/packages/sdk/dist/__tests__/e2e-owner-review.test.js.map +0 -1
  221. package/packages/sdk/dist/__tests__/facade.test.d.ts +0 -2
  222. package/packages/sdk/dist/__tests__/facade.test.d.ts.map +0 -1
  223. package/packages/sdk/dist/__tests__/facade.test.js +0 -305
  224. package/packages/sdk/dist/__tests__/facade.test.js.map +0 -1
  225. package/packages/sdk/dist/__tests__/integration.test.d.ts +0 -2
  226. package/packages/sdk/dist/__tests__/integration.test.d.ts.map +0 -1
  227. package/packages/sdk/dist/__tests__/integration.test.js +0 -205
  228. package/packages/sdk/dist/__tests__/integration.test.js.map +0 -1
  229. package/packages/sdk/dist/__tests__/pty.test.d.ts +0 -2
  230. package/packages/sdk/dist/__tests__/pty.test.d.ts.map +0 -1
  231. package/packages/sdk/dist/__tests__/pty.test.js +0 -20
  232. package/packages/sdk/dist/__tests__/pty.test.js.map +0 -1
  233. package/packages/sdk/dist/__tests__/quickstart.test.d.ts +0 -2
  234. package/packages/sdk/dist/__tests__/quickstart.test.d.ts.map +0 -1
  235. package/packages/sdk/dist/__tests__/quickstart.test.js +0 -176
  236. package/packages/sdk/dist/__tests__/quickstart.test.js.map +0 -1
  237. package/packages/sdk/dist/__tests__/spawn-from-env.test.d.ts +0 -2
  238. package/packages/sdk/dist/__tests__/spawn-from-env.test.d.ts.map +0 -1
  239. package/packages/sdk/dist/__tests__/spawn-from-env.test.js +0 -222
  240. package/packages/sdk/dist/__tests__/spawn-from-env.test.js.map +0 -1
  241. package/packages/sdk/dist/__tests__/unit.test.d.ts +0 -2
  242. package/packages/sdk/dist/__tests__/unit.test.d.ts.map +0 -1
  243. package/packages/sdk/dist/__tests__/unit.test.js +0 -357
  244. package/packages/sdk/dist/__tests__/unit.test.js.map +0 -1
  245. package/packages/sdk-py/agent_relay/__init__.py +0 -21
  246. package/packages/sdk-py/agent_relay/models.py +0 -398
@@ -0,0 +1,338 @@
1
+ /**
2
+ * A2A (Agent-to-Agent) protocol data model types.
3
+ */
4
+
5
+ import { randomUUID } from 'node:crypto';
6
+
7
+ // --- Data model ---
8
+
9
+ export interface A2APart {
10
+ text?: string;
11
+ file?: Record<string, unknown>; // FileContent — phase 2
12
+ data?: Record<string, unknown>; // Structured data — phase 2
13
+ }
14
+
15
+ export interface A2AMessage {
16
+ role: 'user' | 'agent';
17
+ parts: A2APart[];
18
+ messageId?: string;
19
+ contextId?: string;
20
+ taskId?: string;
21
+ }
22
+
23
+ export type A2ATaskState =
24
+ | 'submitted'
25
+ | 'working'
26
+ | 'completed'
27
+ | 'failed'
28
+ | 'canceled';
29
+
30
+ export const VALID_TASK_STATES: ReadonlySet<string> = new Set([
31
+ 'submitted',
32
+ 'working',
33
+ 'completed',
34
+ 'failed',
35
+ 'canceled',
36
+ ]);
37
+
38
+ export interface A2ATaskStatus {
39
+ state: A2ATaskState;
40
+ message?: A2AMessage;
41
+ timestamp?: string;
42
+ }
43
+
44
+ export interface A2ATask {
45
+ id: string;
46
+ contextId?: string;
47
+ status: A2ATaskStatus;
48
+ messages: A2AMessage[];
49
+ artifacts: Record<string, unknown>[];
50
+ }
51
+
52
+ export interface A2ASkill {
53
+ id: string;
54
+ name: string;
55
+ description: string;
56
+ }
57
+
58
+ export interface A2AAgentCard {
59
+ name: string;
60
+ description: string;
61
+ url: string;
62
+ version: string;
63
+ capabilities: Record<string, unknown>;
64
+ skills: A2ASkill[];
65
+ defaultInputModes: string[];
66
+ defaultOutputModes: string[];
67
+ }
68
+
69
+ export interface A2AConfig {
70
+ /** Server mode */
71
+ serverPort?: number;
72
+ serverHost?: string;
73
+ /** Client mode */
74
+ targetUrl?: string;
75
+ /** Agent Card registry (known A2A agent URLs) */
76
+ registry?: string[];
77
+ /** Auth */
78
+ authScheme?: 'bearer' | 'api_key' | string;
79
+ authToken?: string;
80
+ /** Agent metadata */
81
+ agentDescription?: string;
82
+ skills?: A2ASkill[];
83
+ }
84
+
85
+ // --- Factories ---
86
+
87
+ export function createA2APart(text?: string): A2APart {
88
+ const part: A2APart = {};
89
+ if (text !== undefined) part.text = text;
90
+ return part;
91
+ }
92
+
93
+ export function createA2AMessage(
94
+ role: 'user' | 'agent',
95
+ parts: A2APart[],
96
+ opts?: { messageId?: string; contextId?: string; taskId?: string },
97
+ ): A2AMessage {
98
+ return {
99
+ role,
100
+ parts,
101
+ messageId: opts?.messageId ?? randomUUID(),
102
+ contextId: opts?.contextId,
103
+ taskId: opts?.taskId,
104
+ };
105
+ }
106
+
107
+ export function createA2ATaskStatus(
108
+ state: A2ATaskState,
109
+ message?: A2AMessage,
110
+ ): A2ATaskStatus {
111
+ return {
112
+ state,
113
+ message,
114
+ timestamp: new Date().toISOString(),
115
+ };
116
+ }
117
+
118
+ export function createA2ATask(
119
+ id: string,
120
+ contextId?: string,
121
+ ): A2ATask {
122
+ return {
123
+ id,
124
+ contextId,
125
+ status: createA2ATaskStatus('submitted'),
126
+ messages: [],
127
+ artifacts: [],
128
+ };
129
+ }
130
+
131
+ export function createA2AAgentCard(
132
+ name: string,
133
+ description: string,
134
+ url: string,
135
+ skills: A2ASkill[] = [],
136
+ ): A2AAgentCard {
137
+ return {
138
+ name,
139
+ description,
140
+ url,
141
+ version: '1.0.0',
142
+ capabilities: { streaming: true, pushNotifications: false },
143
+ skills,
144
+ defaultInputModes: ['text'],
145
+ defaultOutputModes: ['text'],
146
+ };
147
+ }
148
+
149
+ // --- Serialization helpers ---
150
+
151
+ export function a2aPartToDict(part: A2APart): Record<string, unknown> {
152
+ const d: Record<string, unknown> = {};
153
+ if (part.text !== undefined) d.text = part.text;
154
+ if (part.file !== undefined) d.file = part.file;
155
+ if (part.data !== undefined) d.data = part.data;
156
+ return d;
157
+ }
158
+
159
+ export function a2aPartFromDict(d: Record<string, unknown>): A2APart {
160
+ return {
161
+ text: d.text as string | undefined,
162
+ file: d.file as Record<string, unknown> | undefined,
163
+ data: d.data as Record<string, unknown> | undefined,
164
+ };
165
+ }
166
+
167
+ export function a2aMessageToDict(msg: A2AMessage): Record<string, unknown> {
168
+ const d: Record<string, unknown> = {
169
+ role: msg.role,
170
+ parts: msg.parts.map(a2aPartToDict),
171
+ };
172
+ if (msg.messageId !== undefined) d.messageId = msg.messageId;
173
+ if (msg.contextId !== undefined) d.contextId = msg.contextId;
174
+ if (msg.taskId !== undefined) d.taskId = msg.taskId;
175
+ return d;
176
+ }
177
+
178
+ export function a2aMessageFromDict(d: Record<string, unknown>): A2AMessage {
179
+ const parts = ((d.parts as Record<string, unknown>[] | undefined) ?? []).map(a2aPartFromDict);
180
+ return {
181
+ role: d.role as 'user' | 'agent',
182
+ parts,
183
+ messageId: d.messageId as string | undefined,
184
+ contextId: d.contextId as string | undefined,
185
+ taskId: d.taskId as string | undefined,
186
+ };
187
+ }
188
+
189
+ export function a2aMessageGetText(msg: A2AMessage): string {
190
+ return msg.parts
191
+ .filter((p) => p.text)
192
+ .map((p) => p.text!)
193
+ .join(' ');
194
+ }
195
+
196
+ export function a2aTaskStatusToDict(status: A2ATaskStatus): Record<string, unknown> {
197
+ const d: Record<string, unknown> = { state: status.state };
198
+ if (status.message !== undefined) d.message = a2aMessageToDict(status.message);
199
+ if (status.timestamp !== undefined) d.timestamp = status.timestamp;
200
+ return d;
201
+ }
202
+
203
+ export function a2aTaskStatusFromDict(d: Record<string, unknown>): A2ATaskStatus {
204
+ let message: A2AMessage | undefined;
205
+ if (d.message !== undefined && d.message !== null) {
206
+ message = a2aMessageFromDict(d.message as Record<string, unknown>);
207
+ }
208
+ return {
209
+ state: d.state as A2ATaskState,
210
+ message,
211
+ timestamp: d.timestamp as string | undefined,
212
+ };
213
+ }
214
+
215
+ export function a2aTaskToDict(task: A2ATask): Record<string, unknown> {
216
+ return {
217
+ id: task.id,
218
+ contextId: task.contextId,
219
+ status: a2aTaskStatusToDict(task.status),
220
+ messages: task.messages.map(a2aMessageToDict),
221
+ artifacts: task.artifacts,
222
+ };
223
+ }
224
+
225
+ export function a2aTaskFromDict(d: Record<string, unknown>): A2ATask {
226
+ const status = d.status
227
+ ? a2aTaskStatusFromDict(d.status as Record<string, unknown>)
228
+ : createA2ATaskStatus('submitted');
229
+ const messages = ((d.messages as Record<string, unknown>[]) ?? []).map(a2aMessageFromDict);
230
+ return {
231
+ id: d.id as string,
232
+ contextId: d.contextId as string | undefined,
233
+ status,
234
+ messages,
235
+ artifacts: (d.artifacts as Record<string, unknown>[]) ?? [],
236
+ };
237
+ }
238
+
239
+ export function a2aSkillToDict(skill: A2ASkill): Record<string, unknown> {
240
+ return { id: skill.id, name: skill.name, description: skill.description };
241
+ }
242
+
243
+ export function a2aSkillFromDict(d: Record<string, unknown>): A2ASkill {
244
+ return {
245
+ id: d.id as string,
246
+ name: d.name as string,
247
+ description: d.description as string,
248
+ };
249
+ }
250
+
251
+ export function a2aAgentCardToDict(card: A2AAgentCard): Record<string, unknown> {
252
+ return {
253
+ name: card.name,
254
+ description: card.description,
255
+ url: card.url,
256
+ version: card.version,
257
+ capabilities: card.capabilities,
258
+ skills: card.skills.map(a2aSkillToDict),
259
+ defaultInputModes: card.defaultInputModes,
260
+ defaultOutputModes: card.defaultOutputModes,
261
+ };
262
+ }
263
+
264
+ export function a2aAgentCardFromDict(d: Record<string, unknown>): A2AAgentCard {
265
+ const skills = ((d.skills as Record<string, unknown>[]) ?? []).map(a2aSkillFromDict);
266
+ return {
267
+ name: d.name as string,
268
+ description: d.description as string,
269
+ url: d.url as string,
270
+ version: (d.version as string) ?? '1.0.0',
271
+ capabilities: (d.capabilities as Record<string, unknown>) ?? {
272
+ streaming: true,
273
+ pushNotifications: false,
274
+ },
275
+ skills,
276
+ defaultInputModes: (d.defaultInputModes as string[]) ?? ['text'],
277
+ defaultOutputModes: (d.defaultOutputModes as string[]) ?? ['text'],
278
+ };
279
+ }
280
+
281
+ // --- JSON-RPC 2.0 helpers ---
282
+
283
+ export interface JsonRpcRequest {
284
+ jsonrpc: '2.0';
285
+ method: string;
286
+ params: Record<string, unknown>;
287
+ id: string | number;
288
+ }
289
+
290
+ export interface JsonRpcResponse {
291
+ jsonrpc: '2.0';
292
+ result?: unknown;
293
+ error?: { code: number; message: string };
294
+ id: string | number | null;
295
+ }
296
+
297
+ export function makeJsonRpcRequest(
298
+ method: string,
299
+ params: Record<string, unknown>,
300
+ id?: string | number,
301
+ ): JsonRpcRequest {
302
+ return {
303
+ jsonrpc: '2.0',
304
+ method,
305
+ params,
306
+ id: id ?? randomUUID(),
307
+ };
308
+ }
309
+
310
+ export function makeJsonRpcResponse(
311
+ result: unknown,
312
+ id: string | number,
313
+ ): JsonRpcResponse {
314
+ return { jsonrpc: '2.0', result, id };
315
+ }
316
+
317
+ export function makeJsonRpcError(
318
+ code: number,
319
+ message: string,
320
+ id: string | number | null,
321
+ ): JsonRpcResponse {
322
+ return {
323
+ jsonrpc: '2.0',
324
+ error: { code, message },
325
+ id,
326
+ };
327
+ }
328
+
329
+ // Standard JSON-RPC error codes
330
+ export const JSONRPC_PARSE_ERROR = -32700;
331
+ export const JSONRPC_INVALID_REQUEST = -32600;
332
+ export const JSONRPC_METHOD_NOT_FOUND = -32601;
333
+ export const JSONRPC_INVALID_PARAMS = -32602;
334
+ export const JSONRPC_INTERNAL_ERROR = -32603;
335
+
336
+ // A2A-specific error codes
337
+ export const A2A_TASK_NOT_FOUND = -32001;
338
+ export const A2A_TASK_NOT_CANCELABLE = -32002;
@@ -0,0 +1,85 @@
1
+ import { Relay } from '../core.js';
2
+ import { formatRelayMessage, type Message } from '../types.js';
3
+
4
+ type HookResult = {
5
+ continue?: boolean;
6
+ systemMessage?: string;
7
+ };
8
+
9
+ type HookCallback = (...args: unknown[]) => Promise<HookResult>;
10
+
11
+ type HookMatcher = {
12
+ matcher?: string;
13
+ hooks: HookCallback[];
14
+ timeout?: number;
15
+ };
16
+
17
+ type ClaudeOptionsLike = {
18
+ mcpServers?: Record<string, unknown>;
19
+ hooks?: Partial<Record<'PostToolUse' | 'Stop', HookMatcher[]>>;
20
+ };
21
+
22
+ type RelayLike = {
23
+ inbox(): Promise<Message[]>;
24
+ };
25
+
26
+ function appendHook(
27
+ hooks: ClaudeOptionsLike['hooks'],
28
+ event: 'PostToolUse' | 'Stop',
29
+ callback: HookCallback
30
+ ): ClaudeOptionsLike['hooks'] {
31
+ const matchers = [...(hooks?.[event] ?? []), { hooks: [callback] }];
32
+
33
+ return {
34
+ ...hooks,
35
+ [event]: matchers,
36
+ };
37
+ }
38
+
39
+ async function drainInbox(relay: RelayLike): Promise<string | undefined> {
40
+ const messages = await relay.inbox();
41
+ if (messages.length === 0) {
42
+ return undefined;
43
+ }
44
+
45
+ return `New messages from other agents:\n${messages.map((message) => formatRelayMessage(message)).join('\n')}`;
46
+ }
47
+
48
+ /**
49
+ * Attach relay communication to Claude Agent SDK options via MCP server and hooks.
50
+ * @param _name - Agent name for relay registration.
51
+ * @param options - Claude SDK query options to augment.
52
+ * @param relay - Optional pre-configured Relay instance.
53
+ * @returns Augmented options with relaycast MCP server and inbox-draining hooks.
54
+ */
55
+ export function onRelay<TOptions extends ClaudeOptionsLike>(
56
+ _name: string,
57
+ options: TOptions,
58
+ relay: RelayLike = new Relay(_name)
59
+ ): TOptions {
60
+ const mcpServers = {
61
+ ...(options.mcpServers ?? {}),
62
+ relaycast: {
63
+ command: 'agent-relay',
64
+ args: ['mcp'],
65
+ },
66
+ };
67
+
68
+ let hooks = options.hooks;
69
+
70
+ hooks = appendHook(hooks, 'PostToolUse', async () => {
71
+ const systemMessage = await drainInbox(relay);
72
+ return systemMessage ? { systemMessage } : {};
73
+ });
74
+
75
+ hooks = appendHook(hooks, 'Stop', async () => {
76
+ const systemMessage = await drainInbox(relay);
77
+ return systemMessage ? { continue: true, systemMessage } : {};
78
+ });
79
+
80
+ return {
81
+ ...options,
82
+ mcpServers,
83
+ hooks,
84
+ };
85
+ }
@@ -0,0 +1,141 @@
1
+ import { Relay } from '../core.js';
2
+ import { formatRelayInbox, formatRelayMessage, type Message, type MessageCallback } from '../types.js';
3
+
4
+ /**
5
+ * Minimal structural types mirroring the CrewAI JS SDK's Agent and Crew classes.
6
+ * We use duck-typing so callers don't need to import crewai directly.
7
+ */
8
+
9
+ type CrewAITool = {
10
+ tool_name: string;
11
+ description: string;
12
+ execute: (args: Record<string, unknown>) => Promise<string>;
13
+ };
14
+
15
+ type CrewAIAgentLike = {
16
+ role: string;
17
+ tools: any[];
18
+ step_callback?: ((step: any) => void) | null;
19
+ };
20
+
21
+ type CrewAICrewLike = {
22
+ agents: CrewAIAgentLike[];
23
+ task_callback?: ((output: any) => void) | null;
24
+ };
25
+
26
+ type RelayLike = {
27
+ send(to: string, text: string): Promise<void>;
28
+ post(channel: string, text: string): Promise<void>;
29
+ inbox(): Promise<Message[]>;
30
+ agents(): Promise<string[]>;
31
+ onMessage(callback: MessageCallback): () => void;
32
+ };
33
+
34
+ function createRelayTools(relay: RelayLike): CrewAITool[] {
35
+ return [
36
+ {
37
+ tool_name: 'relay_send',
38
+ description: 'Send a direct message to another relay agent.',
39
+ async execute(args) {
40
+ await relay.send(args.to as string, args.text as string);
41
+ return `Sent relay message to ${args.to}.`;
42
+ },
43
+ },
44
+ {
45
+ tool_name: 'relay_inbox',
46
+ description: 'Drain and inspect newly received relay messages.',
47
+ async execute() {
48
+ return formatRelayInbox(await relay.inbox());
49
+ },
50
+ },
51
+ {
52
+ tool_name: 'relay_post',
53
+ description: 'Post a message to a relay channel.',
54
+ async execute(args) {
55
+ await relay.post(args.channel as string, args.text as string);
56
+ return `Posted relay message to #${args.channel}.`;
57
+ },
58
+ },
59
+ {
60
+ tool_name: 'relay_agents',
61
+ description: 'List currently online relay agents.',
62
+ async execute() {
63
+ return (await relay.agents()).join('\n');
64
+ },
65
+ },
66
+ ];
67
+ }
68
+
69
+ /**
70
+ * Attach relay communication tools and message routing to a CrewAI Agent.
71
+ *
72
+ * Adds relay tools to the agent's `tools` array and installs a `step_callback`
73
+ * that receives incoming relay messages.
74
+ *
75
+ * @param agent - A CrewAI Agent instance (or duck-typed equivalent).
76
+ * @param relay - Optional pre-configured Relay instance.
77
+ * @returns Object with an `unsubscribe` function to stop message routing.
78
+ */
79
+ export function onRelay(
80
+ agent: CrewAIAgentLike,
81
+ relay?: RelayLike,
82
+ ): { unsubscribe: () => void } {
83
+ const relayInstance: RelayLike = relay ?? new Relay(agent.role);
84
+ const relayTools = createRelayTools(relayInstance);
85
+
86
+ // Append relay tools to agent's tools array
87
+ for (const tool of relayTools) {
88
+ agent.tools.push(tool);
89
+ }
90
+
91
+ // Install message routing via step_callback
92
+ const originalCallback = agent.step_callback;
93
+
94
+ const unsubscribe = relayInstance.onMessage(async (message) => {
95
+ const formatted = formatRelayMessage(message);
96
+
97
+ // Route relay messages through the original callback if one exists
98
+ if (originalCallback) {
99
+ originalCallback({ relay_message: formatted });
100
+ }
101
+ });
102
+
103
+ // Compose original callback with relay step forwarding
104
+ if (originalCallback) {
105
+ agent.step_callback = (step: any) => {
106
+ // Forward non-relay steps to original callback
107
+ if (!step?.relay_message) {
108
+ originalCallback(step);
109
+ }
110
+ };
111
+ }
112
+
113
+ return { unsubscribe };
114
+ }
115
+
116
+ /**
117
+ * Attach relay communication tools to all agents in a CrewAI Crew.
118
+ *
119
+ * @param crew - A CrewAI Crew instance (or duck-typed equivalent).
120
+ * @param relay - Optional pre-configured Relay instance.
121
+ * @returns Object with an `unsubscribe` function to stop all message routing.
122
+ */
123
+ export function onCrewRelay(
124
+ crew: CrewAICrewLike,
125
+ relay?: RelayLike,
126
+ ): { unsubscribe: () => void } {
127
+ const unsubscribers: Array<() => void> = [];
128
+
129
+ for (const agent of crew.agents) {
130
+ const result = onRelay(agent, relay);
131
+ unsubscribers.push(result.unsubscribe);
132
+ }
133
+
134
+ return {
135
+ unsubscribe() {
136
+ for (const unsub of unsubscribers) {
137
+ unsub();
138
+ }
139
+ },
140
+ };
141
+ }
@@ -0,0 +1,139 @@
1
+ import { Relay } from '../core.js';
2
+ import { formatRelayInbox, formatRelayMessage, type Message, type MessageCallback } from '../types.js';
3
+
4
+ type JsonObjectSchema = {
5
+ type: 'object';
6
+ properties: Record<string, Record<string, unknown>>;
7
+ required: string[];
8
+ };
9
+
10
+ type FunctionToolLike = {
11
+ name: string;
12
+ description: string;
13
+ };
14
+
15
+ type ToolUnionLike = FunctionToolLike;
16
+
17
+ type RunnerLike = {
18
+ runAsync(params: {
19
+ userId: string;
20
+ sessionId: string;
21
+ newMessage: { role: string; parts: Array<{ text: string }> };
22
+ }): AsyncGenerator<unknown, void, undefined>;
23
+ };
24
+
25
+ type LlmAgentLike = {
26
+ name: string;
27
+ tools: ToolUnionLike[];
28
+ };
29
+
30
+ type RelayLike = {
31
+ send(to: string, text: string): Promise<void>;
32
+ post(channel: string, text: string): Promise<void>;
33
+ inbox(): Promise<Message[]>;
34
+ agents(): Promise<string[]>;
35
+ onMessage(callback: MessageCallback): () => void;
36
+ };
37
+
38
+ interface GoogleAdkRelayOptions {
39
+ /** Google ADK LlmAgent instance. */
40
+ agent: LlmAgentLike;
41
+ /** Optional Runner for routing incoming messages to the agent. */
42
+ runner?: RunnerLike;
43
+ /** User ID for runner sessions. Defaults to 'relay'. */
44
+ userId?: string;
45
+ /** Session ID for runner sessions. Defaults to 'relay-session'. */
46
+ sessionId?: string;
47
+ }
48
+
49
+ /**
50
+ * Create a FunctionTool-shaped object for Google ADK.
51
+ * We construct the tool objects duck-typed to avoid importing the actual
52
+ * FunctionTool class (which requires @google/genai at runtime).
53
+ */
54
+ function createRelayFunctionTools(relay: RelayLike): FunctionToolLike[] {
55
+ // We dynamically import FunctionTool to create real ADK tool instances
56
+ // For now, we build tool-like objects that match the FunctionTool constructor shape
57
+ // and lazily construct them.
58
+ const toolDefs: Array<{
59
+ name: string;
60
+ description: string;
61
+ parameters: JsonObjectSchema;
62
+ execute: (input: Record<string, string>) => Promise<Record<string, unknown>>;
63
+ }> = [
64
+ {
65
+ name: 'relay_send',
66
+ description: 'Send a direct message to another relay agent.',
67
+ parameters: { type: 'object', properties: { to: { type: 'string' }, text: { type: 'string' } }, required: ['to', 'text'] },
68
+ async execute(input) {
69
+ await relay.send(input.to, input.text);
70
+ return { result: `Sent relay message to ${input.to}.` };
71
+ },
72
+ },
73
+ {
74
+ name: 'relay_inbox',
75
+ description: 'Drain and inspect newly received relay messages.',
76
+ parameters: { type: 'object', properties: {}, required: [] },
77
+ async execute() {
78
+ return { result: formatRelayInbox(await relay.inbox()) };
79
+ },
80
+ },
81
+ {
82
+ name: 'relay_post',
83
+ description: 'Post a message to a relay channel.',
84
+ parameters: { type: 'object', properties: { channel: { type: 'string' }, text: { type: 'string' } }, required: ['channel', 'text'] },
85
+ async execute(input) {
86
+ await relay.post(input.channel, input.text);
87
+ return { result: `Posted relay message to #${input.channel}.` };
88
+ },
89
+ },
90
+ {
91
+ name: 'relay_agents',
92
+ description: 'List currently online relay agents.',
93
+ parameters: { type: 'object', properties: {}, required: [] },
94
+ async execute() {
95
+ return { result: (await relay.agents()).join('\n') };
96
+ },
97
+ },
98
+ ];
99
+
100
+ return toolDefs;
101
+ }
102
+
103
+ /**
104
+ * Attach relay communication tools and message routing to a Google ADK agent.
105
+ * @param name - Agent name for relay registration.
106
+ * @param options - Google ADK agent and optional runner configuration.
107
+ * @param relay - Optional pre-configured Relay instance.
108
+ * @returns Object with the augmented agent, an unsubscribe function, and the relay tools added.
109
+ */
110
+ export function onRelay(
111
+ name: string,
112
+ options: GoogleAdkRelayOptions,
113
+ relay: RelayLike = new Relay(name),
114
+ ): { agent: LlmAgentLike; tools: FunctionToolLike[]; unsubscribe: () => void } {
115
+ const { agent, runner, userId = 'relay', sessionId = 'relay-session' } = options;
116
+
117
+ const relayTools = createRelayFunctionTools(relay);
118
+
119
+ // Append relay tools to the agent's tool list
120
+ for (const tool of relayTools) {
121
+ agent.tools.push(tool as ToolUnionLike);
122
+ }
123
+
124
+ let unsubscribe: () => void = () => {};
125
+
126
+ if (runner) {
127
+ unsubscribe = relay.onMessage(async (message: Message) => {
128
+ const prompt = formatRelayMessage(message);
129
+ const content = { role: 'user', parts: [{ text: prompt }] };
130
+
131
+ // Drain the async generator to completion
132
+ for await (const _event of runner.runAsync({ userId, sessionId, newMessage: content })) {
133
+ // Events are consumed; the agent handles them internally.
134
+ }
135
+ });
136
+ }
137
+
138
+ return { agent, tools: relayTools, unsubscribe };
139
+ }
@@ -0,0 +1,6 @@
1
+ export { onRelay as onPiRelay } from './pi.js';
2
+ export { onRelay as onClaudeRelay } from './claude-sdk.js';
3
+ export { onRelay as onCrewAIRelay, onCrewRelay } from './crewai.js';
4
+ export { onRelay as onOpenAIAgentsRelay } from './openai-agents.js';
5
+ export { onRelay as onLangGraphRelay } from './langgraph.js';
6
+ export { onRelay as onGoogleAdkRelay } from './google-adk.js';