@inkeep/agents-run-api 0.0.0-dev-20250910232631

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 (152) hide show
  1. package/LICENSE.md +49 -0
  2. package/README.md +117 -0
  3. package/dist/__tests__/setup.d.ts +4 -0
  4. package/dist/__tests__/setup.d.ts.map +1 -0
  5. package/dist/__tests__/setup.js +80 -0
  6. package/dist/__tests__/utils/testProject.d.ts +18 -0
  7. package/dist/__tests__/utils/testProject.d.ts.map +1 -0
  8. package/dist/__tests__/utils/testProject.js +26 -0
  9. package/dist/__tests__/utils/testRequest.d.ts +8 -0
  10. package/dist/__tests__/utils/testRequest.d.ts.map +1 -0
  11. package/dist/__tests__/utils/testRequest.js +32 -0
  12. package/dist/__tests__/utils/testTenant.d.ts +64 -0
  13. package/dist/__tests__/utils/testTenant.d.ts.map +1 -0
  14. package/dist/__tests__/utils/testTenant.js +71 -0
  15. package/dist/a2a/client.d.ts +182 -0
  16. package/dist/a2a/client.d.ts.map +1 -0
  17. package/dist/a2a/client.js +645 -0
  18. package/dist/a2a/handlers.d.ts +4 -0
  19. package/dist/a2a/handlers.d.ts.map +1 -0
  20. package/dist/a2a/handlers.js +656 -0
  21. package/dist/a2a/transfer.d.ts +18 -0
  22. package/dist/a2a/transfer.d.ts.map +1 -0
  23. package/dist/a2a/transfer.js +22 -0
  24. package/dist/a2a/types.d.ts +63 -0
  25. package/dist/a2a/types.d.ts.map +1 -0
  26. package/dist/a2a/types.js +1 -0
  27. package/dist/agents/Agent.d.ts +151 -0
  28. package/dist/agents/Agent.d.ts.map +1 -0
  29. package/dist/agents/Agent.js +1164 -0
  30. package/dist/agents/ModelFactory.d.ts +62 -0
  31. package/dist/agents/ModelFactory.d.ts.map +1 -0
  32. package/dist/agents/ModelFactory.js +208 -0
  33. package/dist/agents/SystemPromptBuilder.d.ts +14 -0
  34. package/dist/agents/SystemPromptBuilder.d.ts.map +1 -0
  35. package/dist/agents/SystemPromptBuilder.js +62 -0
  36. package/dist/agents/ToolSessionManager.d.ts +53 -0
  37. package/dist/agents/ToolSessionManager.d.ts.map +1 -0
  38. package/dist/agents/ToolSessionManager.js +106 -0
  39. package/dist/agents/artifactTools.d.ts +30 -0
  40. package/dist/agents/artifactTools.d.ts.map +1 -0
  41. package/dist/agents/artifactTools.js +463 -0
  42. package/dist/agents/generateTaskHandler.d.ts +41 -0
  43. package/dist/agents/generateTaskHandler.d.ts.map +1 -0
  44. package/dist/agents/generateTaskHandler.js +350 -0
  45. package/dist/agents/relationTools.d.ts +35 -0
  46. package/dist/agents/relationTools.d.ts.map +1 -0
  47. package/dist/agents/relationTools.js +246 -0
  48. package/dist/agents/types.d.ts +23 -0
  49. package/dist/agents/types.d.ts.map +1 -0
  50. package/dist/agents/types.js +1 -0
  51. package/dist/agents/versions/V1Config.d.ts +21 -0
  52. package/dist/agents/versions/V1Config.d.ts.map +1 -0
  53. package/dist/agents/versions/V1Config.js +285 -0
  54. package/dist/app.d.ts +5 -0
  55. package/dist/app.d.ts.map +1 -0
  56. package/dist/app.js +219 -0
  57. package/dist/data/agentGraph.d.ts +4 -0
  58. package/dist/data/agentGraph.d.ts.map +1 -0
  59. package/dist/data/agentGraph.js +73 -0
  60. package/dist/data/agents.d.ts +4 -0
  61. package/dist/data/agents.d.ts.map +1 -0
  62. package/dist/data/agents.js +78 -0
  63. package/dist/data/conversations.d.ts +59 -0
  64. package/dist/data/conversations.d.ts.map +1 -0
  65. package/dist/data/conversations.js +216 -0
  66. package/dist/data/db/clean.d.ts +6 -0
  67. package/dist/data/db/clean.d.ts.map +1 -0
  68. package/dist/data/db/clean.js +77 -0
  69. package/dist/data/db/dbClient.d.ts +3 -0
  70. package/dist/data/db/dbClient.d.ts.map +1 -0
  71. package/dist/data/db/dbClient.js +13 -0
  72. package/dist/env.d.ts +45 -0
  73. package/dist/env.d.ts.map +1 -0
  74. package/dist/env.js +64 -0
  75. package/dist/handlers/executionHandler.d.ts +36 -0
  76. package/dist/handlers/executionHandler.d.ts.map +1 -0
  77. package/dist/handlers/executionHandler.js +415 -0
  78. package/dist/index.d.ts +11 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +28 -0
  81. package/dist/instrumentation.d.ts +13 -0
  82. package/dist/instrumentation.d.ts.map +1 -0
  83. package/dist/instrumentation.js +66 -0
  84. package/dist/logger.d.ts +4 -0
  85. package/dist/logger.d.ts.map +1 -0
  86. package/dist/logger.js +32 -0
  87. package/dist/middleware/api-key-auth.d.ts +22 -0
  88. package/dist/middleware/api-key-auth.d.ts.map +1 -0
  89. package/dist/middleware/api-key-auth.js +139 -0
  90. package/dist/middleware/index.d.ts +2 -0
  91. package/dist/middleware/index.d.ts.map +1 -0
  92. package/dist/middleware/index.js +1 -0
  93. package/dist/openapi.d.ts +2 -0
  94. package/dist/openapi.d.ts.map +1 -0
  95. package/dist/openapi.js +36 -0
  96. package/dist/routes/agents.d.ts +10 -0
  97. package/dist/routes/agents.d.ts.map +1 -0
  98. package/dist/routes/agents.js +158 -0
  99. package/dist/routes/chat.d.ts +10 -0
  100. package/dist/routes/chat.d.ts.map +1 -0
  101. package/dist/routes/chat.js +307 -0
  102. package/dist/routes/chatDataStream.d.ts +10 -0
  103. package/dist/routes/chatDataStream.d.ts.map +1 -0
  104. package/dist/routes/chatDataStream.js +185 -0
  105. package/dist/routes/mcp.d.ts +10 -0
  106. package/dist/routes/mcp.d.ts.map +1 -0
  107. package/dist/routes/mcp.js +500 -0
  108. package/dist/tracer.d.ts +24 -0
  109. package/dist/tracer.d.ts.map +1 -0
  110. package/dist/tracer.js +107 -0
  111. package/dist/types/chat.d.ts +25 -0
  112. package/dist/types/chat.d.ts.map +1 -0
  113. package/dist/types/chat.js +1 -0
  114. package/dist/types/execution-context.d.ts +14 -0
  115. package/dist/types/execution-context.d.ts.map +1 -0
  116. package/dist/types/execution-context.js +14 -0
  117. package/dist/utils/agent-operations.d.ts +93 -0
  118. package/dist/utils/agent-operations.d.ts.map +1 -0
  119. package/dist/utils/agent-operations.js +78 -0
  120. package/dist/utils/artifact-component-schema.d.ts +29 -0
  121. package/dist/utils/artifact-component-schema.d.ts.map +1 -0
  122. package/dist/utils/artifact-component-schema.js +119 -0
  123. package/dist/utils/artifact-parser.d.ts +71 -0
  124. package/dist/utils/artifact-parser.d.ts.map +1 -0
  125. package/dist/utils/artifact-parser.js +253 -0
  126. package/dist/utils/cleanup.d.ts +19 -0
  127. package/dist/utils/cleanup.d.ts.map +1 -0
  128. package/dist/utils/cleanup.js +66 -0
  129. package/dist/utils/data-component-schema.d.ts +6 -0
  130. package/dist/utils/data-component-schema.d.ts.map +1 -0
  131. package/dist/utils/data-component-schema.js +43 -0
  132. package/dist/utils/graph-session.d.ts +230 -0
  133. package/dist/utils/graph-session.d.ts.map +1 -0
  134. package/dist/utils/graph-session.js +1199 -0
  135. package/dist/utils/incremental-stream-parser.d.ts +62 -0
  136. package/dist/utils/incremental-stream-parser.d.ts.map +1 -0
  137. package/dist/utils/incremental-stream-parser.js +330 -0
  138. package/dist/utils/response-formatter.d.ts +26 -0
  139. package/dist/utils/response-formatter.d.ts.map +1 -0
  140. package/dist/utils/response-formatter.js +158 -0
  141. package/dist/utils/stream-helpers.d.ts +186 -0
  142. package/dist/utils/stream-helpers.d.ts.map +1 -0
  143. package/dist/utils/stream-helpers.js +603 -0
  144. package/dist/utils/stream-registry.d.ts +18 -0
  145. package/dist/utils/stream-registry.d.ts.map +1 -0
  146. package/dist/utils/stream-registry.js +33 -0
  147. package/package.json +95 -0
  148. package/templates/v1/artifact.xml +7 -0
  149. package/templates/v1/data-component.xml +9 -0
  150. package/templates/v1/system-prompt.xml +52 -0
  151. package/templates/v1/thinking-preparation.xml +34 -0
  152. package/templates/v1/tool.xml +12 -0
@@ -0,0 +1,656 @@
1
+ import { createMessage, createTask, getRequestExecutionContext, TaskState, updateTask, } from '@inkeep/agents-core';
2
+ import { streamSSE } from 'hono/streaming';
3
+ import { nanoid } from 'nanoid';
4
+ import dbClient from '../data/db/dbClient';
5
+ import { getLogger } from '../logger';
6
+ const logger = getLogger('a2aHandler');
7
+ export async function a2aHandler(c, agent) {
8
+ try {
9
+ const rpcRequest = await c.req.json();
10
+ // Validate JSON-RPC format
11
+ if (rpcRequest.jsonrpc !== '2.0') {
12
+ return c.json({
13
+ jsonrpc: '2.0',
14
+ error: {
15
+ code: -32600,
16
+ message: 'Invalid Request - must be JSON-RPC 2.0',
17
+ },
18
+ id: rpcRequest.id,
19
+ });
20
+ }
21
+ // Handle different A2A methods (including Google's protocol methods)
22
+ switch (rpcRequest.method) {
23
+ // Google A2A Protocol Methods
24
+ case 'message/send':
25
+ return await handleMessageSend(c, agent, rpcRequest);
26
+ case 'message/stream':
27
+ return await handleMessageStream(c, agent, rpcRequest);
28
+ case 'tasks/get':
29
+ return await handleTasksGet(c, agent, rpcRequest);
30
+ case 'tasks/cancel':
31
+ return await handleTasksCancel(c, agent, rpcRequest);
32
+ case 'tasks/resubscribe':
33
+ return await handleTasksResubscribe(c, agent, rpcRequest);
34
+ // Legacy/simplified methods
35
+ case 'agent.invoke':
36
+ return await handleAgentInvoke(c, agent, rpcRequest);
37
+ case 'agent.getCapabilities':
38
+ return await handleGetCapabilities(c, agent, rpcRequest);
39
+ case 'agent.getStatus':
40
+ return await handleGetStatus(c, agent, rpcRequest);
41
+ default:
42
+ return c.json({
43
+ jsonrpc: '2.0',
44
+ error: {
45
+ code: -32601,
46
+ message: `Method not found: ${rpcRequest.method}`,
47
+ },
48
+ id: rpcRequest.id,
49
+ });
50
+ }
51
+ }
52
+ catch (error) {
53
+ console.error('A2A Handler Error:', error);
54
+ return c.json({
55
+ jsonrpc: '2.0',
56
+ error: {
57
+ code: -32700,
58
+ message: 'Parse error',
59
+ },
60
+ id: null,
61
+ });
62
+ }
63
+ }
64
+ async function handleMessageSend(c, agent, request) {
65
+ try {
66
+ const params = request.params;
67
+ const executionContext = getRequestExecutionContext(c);
68
+ const { graphId } = executionContext;
69
+ // Convert to our internal task format
70
+ const task = {
71
+ id: nanoid(),
72
+ input: {
73
+ parts: params.message.parts.map((part) => ({
74
+ kind: part.kind,
75
+ text: part.kind === 'text' ? part.text : undefined,
76
+ data: part.kind === 'data' ? part.data : undefined,
77
+ })),
78
+ },
79
+ context: {
80
+ conversationId: params.message.contextId,
81
+ metadata: {
82
+ blocking: params.configuration?.blocking ?? false,
83
+ custom: { graph_id: graphId || '' },
84
+ // Pass through streaming metadata from the original message
85
+ ...params.message.metadata,
86
+ },
87
+ },
88
+ };
89
+ // Enhanced contextId resolution for delegation
90
+ let effectiveContextId = params.message?.contextId;
91
+ // If contextId is missing or 'default', try to get it from task.context
92
+ if (!effectiveContextId || effectiveContextId === 'default') {
93
+ effectiveContextId = task.context?.conversationId;
94
+ }
95
+ // If still missing, try to extract from metadata
96
+ if (!effectiveContextId || effectiveContextId === 'default') {
97
+ if (params.message?.metadata?.conversationId &&
98
+ params.message.metadata.conversationId !== 'default') {
99
+ effectiveContextId = params.message.metadata.conversationId;
100
+ }
101
+ }
102
+ // Final fallback
103
+ if (!effectiveContextId || effectiveContextId === 'default') {
104
+ effectiveContextId = 'default';
105
+ }
106
+ // Enhanced message content handling
107
+ let _messageContent = '';
108
+ try {
109
+ if (params.message && Object.keys(params.message).length > 0) {
110
+ _messageContent = JSON.stringify(params.message);
111
+ }
112
+ else {
113
+ // Fallback: create a minimal message structure
114
+ _messageContent = JSON.stringify({
115
+ role: 'agent',
116
+ parts: [{ text: 'Delegation task', kind: 'text' }],
117
+ contextId: effectiveContextId,
118
+ messageId: task.id,
119
+ kind: 'message',
120
+ });
121
+ logger.warn({
122
+ taskId: task.id,
123
+ agentId: agent.agentId,
124
+ originalMessage: params.message,
125
+ }, 'Created fallback message content for empty delegation message');
126
+ }
127
+ }
128
+ catch (error) {
129
+ logger.error({ error, taskId: task.id }, 'Failed to serialize message');
130
+ _messageContent = JSON.stringify({
131
+ error: 'Failed to serialize message',
132
+ taskId: task.id,
133
+ contextId: effectiveContextId,
134
+ parts: [{ text: 'Error in delegation', kind: 'text' }],
135
+ });
136
+ }
137
+ logger.info({
138
+ originalContextId: params.message.contextId,
139
+ taskContextId: task.context?.conversationId,
140
+ metadataContextId: params.message.metadata?.conversationId,
141
+ finalContextId: effectiveContextId,
142
+ agentId: agent.agentId,
143
+ }, 'A2A contextId resolution for delegation');
144
+ // --- Persist the task in the DB ---
145
+ await createTask(dbClient)({
146
+ id: task.id,
147
+ tenantId: agent.tenantId,
148
+ projectId: agent.projectId,
149
+ contextId: effectiveContextId,
150
+ status: 'working',
151
+ metadata: {
152
+ conversation_id: effectiveContextId,
153
+ message_id: params.message.messageId || '',
154
+ created_at: new Date().toISOString(),
155
+ updated_at: new Date().toISOString(),
156
+ agent_id: agent.agentId,
157
+ graph_id: graphId || '',
158
+ stream_request_id: params.message.metadata?.stream_request_id,
159
+ },
160
+ agentId: agent.agentId,
161
+ createdAt: new Date().toISOString(),
162
+ updatedAt: new Date().toISOString(),
163
+ });
164
+ logger.info({ metadata: params.message.metadata }, 'message metadata');
165
+ // --- Store A2A message in database if this is agent-to-agent communication ---
166
+ // TODO: we need to identify external agent requests through propoer auth headers
167
+ if (params.message.metadata?.fromAgentId || params.message.metadata?.fromExternalAgentId) {
168
+ const messageText = params.message.parts
169
+ .filter((part) => part.kind === 'text' && 'text' in part && part.text)
170
+ .map((part) => part.text)
171
+ .join(' ');
172
+ try {
173
+ const messageData = {
174
+ id: nanoid(),
175
+ tenantId: agent.tenantId,
176
+ projectId: agent.projectId,
177
+ conversationId: effectiveContextId,
178
+ role: 'agent',
179
+ content: {
180
+ text: messageText,
181
+ },
182
+ visibility: params.message.metadata?.fromExternalAgentId ? 'external' : 'internal',
183
+ messageType: 'a2a-request',
184
+ taskId: task.id,
185
+ };
186
+ // Set appropriate agent tracking fields
187
+ if (params.message.metadata?.fromAgentId) {
188
+ // Internal agent communication
189
+ messageData.fromAgentId = params.message.metadata.fromAgentId;
190
+ messageData.toAgentId = agent.agentId;
191
+ }
192
+ else if (params.message.metadata?.fromExternalAgentId) {
193
+ // External agent communication
194
+ messageData.fromExternalAgentId = params.message.metadata.fromExternalAgentId;
195
+ messageData.toAgentId = agent.agentId;
196
+ }
197
+ await createMessage(dbClient)(messageData);
198
+ logger.info({
199
+ fromAgentId: params.message.metadata.fromAgentId,
200
+ fromExternalAgentId: params.message.metadata.fromExternalAgentId,
201
+ toAgentId: agent.agentId,
202
+ conversationId: effectiveContextId,
203
+ messageType: 'a2a-request',
204
+ taskId: task.id,
205
+ }, 'A2A message stored in database');
206
+ }
207
+ catch (error) {
208
+ logger.error({
209
+ error,
210
+ fromAgentId: params.message.metadata.fromAgentId,
211
+ fromExternalAgentId: params.message.metadata.fromExternalAgentId,
212
+ toAgentId: agent.agentId,
213
+ conversationId: effectiveContextId,
214
+ }, 'Failed to store A2A message in database');
215
+ }
216
+ }
217
+ // Execute the task
218
+ const result = await agent.taskHandler(task);
219
+ // --- Update the task in the DB with result ---
220
+ await updateTask(dbClient)({
221
+ taskId: task.id,
222
+ data: {
223
+ status: result.status.state.toLowerCase(),
224
+ metadata: {
225
+ conversation_id: params.message.contextId || '',
226
+ message_id: params.message.messageId || '',
227
+ created_at: new Date().toISOString(),
228
+ updated_at: new Date().toISOString(),
229
+ agent_id: agent.agentId,
230
+ graph_id: graphId || '',
231
+ },
232
+ },
233
+ });
234
+ // Check if the result contains a transfer indication
235
+ const transferArtifact = result.artifacts?.find((artifact) => artifact.parts?.some((part) => part.kind === 'data' &&
236
+ part.data &&
237
+ typeof part.data === 'object' &&
238
+ part.data.type === 'transfer'));
239
+ if (transferArtifact) {
240
+ const transferPart = transferArtifact.parts?.find((part) => part.kind === 'data' &&
241
+ part.data &&
242
+ typeof part.data === 'object' &&
243
+ part.data.type === 'transfer');
244
+ if (transferPart && transferPart.kind === 'data' && transferPart.data) {
245
+ logger.info({ transferPart }, 'transferPart');
246
+ // Return a transfer response instead of normal task/message response
247
+ return c.json({
248
+ jsonrpc: '2.0',
249
+ result: {
250
+ kind: 'task',
251
+ contextId: params.message.contextId,
252
+ id: task.id,
253
+ status: {
254
+ state: TaskState.Completed,
255
+ timestamp: new Date().toISOString(),
256
+ },
257
+ artifacts: [
258
+ {
259
+ artifactId: nanoid(),
260
+ parts: [
261
+ {
262
+ kind: 'data',
263
+ data: {
264
+ type: 'transfer',
265
+ targetAgentId: transferPart.data.target,
266
+ },
267
+ },
268
+ {
269
+ kind: 'text',
270
+ text: transferPart.data.reason || 'Agent requested transfer',
271
+ },
272
+ ],
273
+ },
274
+ ],
275
+ },
276
+ id: request.id,
277
+ });
278
+ }
279
+ }
280
+ // Convert A2ATaskResult status to schema TaskStatus
281
+ const taskStatus = {
282
+ state: result.status.state,
283
+ timestamp: new Date().toISOString(),
284
+ // Don't include message field since it expects Message object, not string
285
+ };
286
+ // Convert back to Google A2A format
287
+ if (params.configuration?.blocking === false) {
288
+ // Return a Task for non-blocking requests
289
+ const taskResponse = {
290
+ id: task.id,
291
+ contextId: params.message.contextId || nanoid(),
292
+ status: taskStatus,
293
+ artifacts: result.artifacts,
294
+ kind: 'task',
295
+ };
296
+ return c.json({
297
+ jsonrpc: '2.0',
298
+ result: taskResponse,
299
+ id: request.id,
300
+ });
301
+ }
302
+ // Return a Message for blocking requests
303
+ const messageResponse = {
304
+ messageId: nanoid(),
305
+ parts: result.artifacts?.[0]?.parts || [
306
+ {
307
+ kind: 'text',
308
+ text: 'Task completed successfully',
309
+ },
310
+ ],
311
+ role: 'agent',
312
+ taskId: task.id,
313
+ contextId: params.message.contextId,
314
+ kind: 'message',
315
+ };
316
+ return c.json({
317
+ jsonrpc: '2.0',
318
+ result: messageResponse,
319
+ id: request.id,
320
+ });
321
+ }
322
+ catch (error) {
323
+ return c.json({
324
+ jsonrpc: '2.0',
325
+ error: {
326
+ code: -32603,
327
+ message: 'Internal error during message send',
328
+ data: error instanceof Error ? error.message : 'Unknown error',
329
+ },
330
+ id: request.id,
331
+ });
332
+ }
333
+ }
334
+ async function handleMessageStream(c, agent, request) {
335
+ try {
336
+ const params = request.params;
337
+ const executionContext = getRequestExecutionContext(c);
338
+ const { graphId } = executionContext;
339
+ // Check if agent supports streaming
340
+ if (!agent.agentCard.capabilities.streaming) {
341
+ return c.json({
342
+ jsonrpc: '2.0',
343
+ error: {
344
+ code: -32604,
345
+ message: 'Agent does not support streaming',
346
+ },
347
+ id: request.id,
348
+ });
349
+ }
350
+ // Convert to our internal task format
351
+ const task = {
352
+ id: nanoid(),
353
+ input: {
354
+ parts: params.message.parts.map((part) => ({
355
+ kind: part.kind,
356
+ text: part.kind === 'text' ? part.text : undefined,
357
+ data: part.kind === 'data' ? part.data : undefined,
358
+ })),
359
+ },
360
+ context: {
361
+ conversationId: params.message.contextId,
362
+ metadata: {
363
+ blocking: false, // Streaming is always non-blocking
364
+ custom: { graph_id: graphId || '' },
365
+ },
366
+ },
367
+ };
368
+ // Return SSE stream
369
+ return streamSSE(c, async (stream) => {
370
+ try {
371
+ // Initial task acknowledgment
372
+ const initialTask = {
373
+ id: task.id,
374
+ contextId: params.message.contextId || nanoid(),
375
+ status: {
376
+ state: TaskState.Working,
377
+ timestamp: new Date().toISOString(),
378
+ },
379
+ artifacts: [],
380
+ kind: 'task',
381
+ };
382
+ // Send initial task status
383
+ await stream.writeSSE({
384
+ data: JSON.stringify({
385
+ jsonrpc: '2.0',
386
+ result: initialTask,
387
+ id: request.id,
388
+ }),
389
+ });
390
+ // Execute the task with streaming
391
+ const result = await agent.taskHandler(task);
392
+ // Check for transfer first
393
+ const transferArtifact = result.artifacts?.find((artifact) => artifact.parts?.some((part) => part.kind === 'data' &&
394
+ part.data &&
395
+ typeof part.data === 'object' &&
396
+ part.data.type === 'transfer'));
397
+ if (transferArtifact) {
398
+ const transferPart = transferArtifact.parts?.find((part) => part.kind === 'data' &&
399
+ part.data &&
400
+ typeof part.data === 'object' &&
401
+ part.data.type === 'transfer');
402
+ if (transferPart && transferPart.kind === 'data' && transferPart.data) {
403
+ // Stream transfer response
404
+ await stream.writeSSE({
405
+ data: JSON.stringify({
406
+ jsonrpc: '2.0',
407
+ result: {
408
+ type: 'transfer',
409
+ target: transferPart.data.target,
410
+ task_id: task.id,
411
+ reason: transferPart.data.reason || 'Agent requested transfer',
412
+ original_message: transferPart.data.original_message,
413
+ context: {
414
+ conversationId: params.message.contextId,
415
+ tenantId: agent.tenantId,
416
+ transfer_context: result.artifacts,
417
+ },
418
+ },
419
+ id: request.id,
420
+ }),
421
+ });
422
+ return;
423
+ }
424
+ }
425
+ // Stream regular message response
426
+ const messageResponse = {
427
+ messageId: nanoid(),
428
+ parts: result.artifacts?.[0]?.parts || [
429
+ {
430
+ kind: 'text',
431
+ text: 'Task completed successfully',
432
+ },
433
+ ],
434
+ role: 'agent',
435
+ taskId: task.id,
436
+ contextId: params.message.contextId,
437
+ kind: 'message',
438
+ };
439
+ await stream.writeSSE({
440
+ data: JSON.stringify({
441
+ jsonrpc: '2.0',
442
+ result: messageResponse,
443
+ id: request.id,
444
+ }),
445
+ });
446
+ // Send final task completion status
447
+ const completedTask = {
448
+ ...initialTask,
449
+ status: {
450
+ state: TaskState.Completed,
451
+ timestamp: new Date().toISOString(),
452
+ },
453
+ artifacts: result.artifacts,
454
+ };
455
+ await stream.writeSSE({
456
+ data: JSON.stringify({
457
+ jsonrpc: '2.0',
458
+ result: completedTask,
459
+ id: request.id,
460
+ }),
461
+ });
462
+ }
463
+ catch (error) {
464
+ console.error('Error in stream execution:', error);
465
+ // Send error as SSE event
466
+ await stream.writeSSE({
467
+ data: JSON.stringify({
468
+ jsonrpc: '2.0',
469
+ error: {
470
+ code: -32603,
471
+ message: 'Internal error during streaming execution',
472
+ data: error instanceof Error ? error.message : 'Unknown error',
473
+ },
474
+ id: request.id,
475
+ }),
476
+ });
477
+ }
478
+ });
479
+ }
480
+ catch (error) {
481
+ return c.json({
482
+ jsonrpc: '2.0',
483
+ error: {
484
+ code: -32603,
485
+ message: 'Internal error during message stream setup',
486
+ data: error instanceof Error ? error.message : 'Unknown error',
487
+ },
488
+ id: request.id,
489
+ });
490
+ }
491
+ }
492
+ async function handleTasksGet(c, _agent, request) {
493
+ try {
494
+ const params = request.params;
495
+ // For now, return a mock task since we don't have persistent storage
496
+ const task = {
497
+ id: params.id,
498
+ contextId: nanoid(),
499
+ status: {
500
+ state: TaskState.Completed,
501
+ timestamp: new Date().toISOString(),
502
+ },
503
+ artifacts: [
504
+ {
505
+ artifactId: nanoid(),
506
+ parts: [
507
+ {
508
+ kind: 'text',
509
+ text: `Task ${params.id} completed successfully`,
510
+ },
511
+ ],
512
+ },
513
+ ],
514
+ kind: 'task',
515
+ };
516
+ return c.json({
517
+ jsonrpc: '2.0',
518
+ result: task,
519
+ id: request.id,
520
+ });
521
+ }
522
+ catch (error) {
523
+ return c.json({
524
+ jsonrpc: '2.0',
525
+ error: {
526
+ code: -32603,
527
+ message: 'Internal error getting task',
528
+ data: error instanceof Error ? error.message : 'Unknown error',
529
+ },
530
+ id: request.id,
531
+ });
532
+ }
533
+ }
534
+ async function handleTasksCancel(c, _agent, request) {
535
+ try {
536
+ const _params = request.params;
537
+ // For now, just return success
538
+ return c.json({
539
+ jsonrpc: '2.0',
540
+ result: { success: true },
541
+ id: request.id,
542
+ });
543
+ }
544
+ catch (error) {
545
+ return c.json({
546
+ jsonrpc: '2.0',
547
+ error: {
548
+ code: -32603,
549
+ message: 'Internal error canceling task',
550
+ data: error instanceof Error ? error.message : 'Unknown error',
551
+ },
552
+ id: request.id,
553
+ });
554
+ }
555
+ }
556
+ async function handleAgentInvoke(c, agent, request) {
557
+ try {
558
+ const task = request.params;
559
+ const result = await agent.taskHandler(task);
560
+ return c.json({
561
+ jsonrpc: '2.0',
562
+ result,
563
+ id: request.id,
564
+ });
565
+ }
566
+ catch (error) {
567
+ return c.json({
568
+ jsonrpc: '2.0',
569
+ error: {
570
+ code: -32603,
571
+ message: 'Internal error during agent invocation',
572
+ data: error instanceof Error ? error.message : 'Unknown error',
573
+ },
574
+ id: request.id,
575
+ });
576
+ }
577
+ }
578
+ async function handleGetCapabilities(c, agent, request) {
579
+ return c.json({
580
+ jsonrpc: '2.0',
581
+ result: agent.agentCard.capabilities,
582
+ id: request.id,
583
+ });
584
+ }
585
+ async function handleGetStatus(c, agent, request) {
586
+ return c.json({
587
+ jsonrpc: '2.0',
588
+ result: { status: 'ready', agentId: agent.agentId },
589
+ id: request.id,
590
+ });
591
+ }
592
+ async function handleTasksResubscribe(c, agent, request) {
593
+ try {
594
+ const params = request.params;
595
+ // Check if agent supports streaming
596
+ if (!agent.agentCard.capabilities.streaming) {
597
+ return c.json({
598
+ jsonrpc: '2.0',
599
+ error: {
600
+ code: -32604,
601
+ message: 'Agent does not support streaming for resubscription',
602
+ },
603
+ id: request.id,
604
+ });
605
+ }
606
+ // For now, return SSE stream that immediately provides task status
607
+ // In a full implementation, this would reconnect to an existing task's stream
608
+ return streamSSE(c, async (stream) => {
609
+ try {
610
+ // Mock task status for resubscription
611
+ const task = {
612
+ id: params.taskId,
613
+ contextId: nanoid(),
614
+ status: {
615
+ state: TaskState.Completed,
616
+ timestamp: new Date().toISOString(),
617
+ },
618
+ artifacts: [],
619
+ kind: 'task',
620
+ };
621
+ await stream.writeSSE({
622
+ data: JSON.stringify({
623
+ jsonrpc: '2.0',
624
+ result: task,
625
+ id: request.id,
626
+ }),
627
+ });
628
+ }
629
+ catch (error) {
630
+ console.error('Error in task resubscription:', error);
631
+ await stream.writeSSE({
632
+ data: JSON.stringify({
633
+ jsonrpc: '2.0',
634
+ error: {
635
+ code: -32603,
636
+ message: 'Internal error during task resubscription',
637
+ data: error instanceof Error ? error.message : 'Unknown error',
638
+ },
639
+ id: request.id,
640
+ }),
641
+ });
642
+ }
643
+ });
644
+ }
645
+ catch (error) {
646
+ return c.json({
647
+ jsonrpc: '2.0',
648
+ error: {
649
+ code: -32603,
650
+ message: 'Internal error during task resubscription setup',
651
+ data: error instanceof Error ? error.message : 'Unknown error',
652
+ },
653
+ id: request.id,
654
+ });
655
+ }
656
+ }
@@ -0,0 +1,18 @@
1
+ import type { TransferResponse } from './types';
2
+ /**
3
+ * Executes a transfer by sending the original message to the target agent
4
+ */
5
+ export declare function executeTransfer({ tenantId, threadId, projectId, targetAgentId, }: {
6
+ tenantId: string;
7
+ threadId: string;
8
+ projectId: string;
9
+ targetAgentId: string;
10
+ }): Promise<{
11
+ success: boolean;
12
+ targetAgentId: string;
13
+ }>;
14
+ /**
15
+ * Checks if a response is a transfer response
16
+ */
17
+ export declare function isTransferResponse(result: any): result is TransferResponse;
18
+ //# sourceMappingURL=transfer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../../src/a2a/transfer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGhD;;GAEG;AACH,wBAAsB,eAAe,CAAC,EACpC,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,aAAa,GACd,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC;IACV,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAQD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,IAAI,gBAAgB,CAI1E"}