@inkeep/agents-run-api 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/README.md +117 -0
  2. package/dist/AgentExecutionServer.d.ts +23 -0
  3. package/dist/AgentExecutionServer.d.ts.map +1 -0
  4. package/dist/AgentExecutionServer.js +32 -0
  5. package/dist/__tests__/setup.d.ts +4 -0
  6. package/dist/__tests__/setup.d.ts.map +1 -0
  7. package/dist/__tests__/setup.js +50 -0
  8. package/dist/__tests__/utils/testProject.d.ts +18 -0
  9. package/dist/__tests__/utils/testProject.d.ts.map +1 -0
  10. package/dist/__tests__/utils/testProject.js +26 -0
  11. package/dist/__tests__/utils/testRequest.d.ts +8 -0
  12. package/dist/__tests__/utils/testRequest.d.ts.map +1 -0
  13. package/dist/__tests__/utils/testRequest.js +32 -0
  14. package/dist/__tests__/utils/testTenant.d.ts +64 -0
  15. package/dist/__tests__/utils/testTenant.d.ts.map +1 -0
  16. package/dist/__tests__/utils/testTenant.js +71 -0
  17. package/dist/a2a/client.d.ts +182 -0
  18. package/dist/a2a/client.d.ts.map +1 -0
  19. package/dist/a2a/client.js +645 -0
  20. package/dist/a2a/handlers.d.ts +4 -0
  21. package/dist/a2a/handlers.d.ts.map +1 -0
  22. package/dist/a2a/handlers.js +657 -0
  23. package/dist/a2a/transfer.d.ts +18 -0
  24. package/dist/a2a/transfer.d.ts.map +1 -0
  25. package/dist/a2a/transfer.js +22 -0
  26. package/dist/a2a/types.d.ts +63 -0
  27. package/dist/a2a/types.d.ts.map +1 -0
  28. package/dist/a2a/types.js +1 -0
  29. package/dist/agents/Agent.d.ts +154 -0
  30. package/dist/agents/Agent.d.ts.map +1 -0
  31. package/dist/agents/Agent.js +1105 -0
  32. package/dist/agents/ModelFactory.d.ts +62 -0
  33. package/dist/agents/ModelFactory.d.ts.map +1 -0
  34. package/dist/agents/ModelFactory.js +208 -0
  35. package/dist/agents/SystemPromptBuilder.d.ts +14 -0
  36. package/dist/agents/SystemPromptBuilder.d.ts.map +1 -0
  37. package/dist/agents/SystemPromptBuilder.js +62 -0
  38. package/dist/agents/ToolSessionManager.d.ts +61 -0
  39. package/dist/agents/ToolSessionManager.d.ts.map +1 -0
  40. package/dist/agents/ToolSessionManager.js +143 -0
  41. package/dist/agents/artifactTools.d.ts +30 -0
  42. package/dist/agents/artifactTools.d.ts.map +1 -0
  43. package/dist/agents/artifactTools.js +463 -0
  44. package/dist/agents/generateTaskHandler.d.ts +41 -0
  45. package/dist/agents/generateTaskHandler.d.ts.map +1 -0
  46. package/dist/agents/generateTaskHandler.js +350 -0
  47. package/dist/agents/relationTools.d.ts +33 -0
  48. package/dist/agents/relationTools.d.ts.map +1 -0
  49. package/dist/agents/relationTools.js +245 -0
  50. package/dist/agents/types.d.ts +23 -0
  51. package/dist/agents/types.d.ts.map +1 -0
  52. package/dist/agents/types.js +1 -0
  53. package/dist/agents/versions/V1Config.d.ts +21 -0
  54. package/dist/agents/versions/V1Config.d.ts.map +1 -0
  55. package/dist/agents/versions/V1Config.js +285 -0
  56. package/dist/app.d.ts +4 -0
  57. package/dist/app.d.ts.map +1 -0
  58. package/dist/app.js +194 -0
  59. package/dist/data/agentGraph.d.ts +4 -0
  60. package/dist/data/agentGraph.d.ts.map +1 -0
  61. package/dist/data/agentGraph.js +73 -0
  62. package/dist/data/agents.d.ts +4 -0
  63. package/dist/data/agents.d.ts.map +1 -0
  64. package/dist/data/agents.js +73 -0
  65. package/dist/data/conversations.d.ts +59 -0
  66. package/dist/data/conversations.d.ts.map +1 -0
  67. package/dist/data/conversations.js +216 -0
  68. package/dist/data/db/clean.d.ts +6 -0
  69. package/dist/data/db/clean.d.ts.map +1 -0
  70. package/dist/data/db/clean.js +77 -0
  71. package/dist/data/db/dbClient.d.ts +3 -0
  72. package/dist/data/db/dbClient.d.ts.map +1 -0
  73. package/dist/data/db/dbClient.js +13 -0
  74. package/dist/env.d.ts +43 -0
  75. package/dist/env.d.ts.map +1 -0
  76. package/dist/env.js +63 -0
  77. package/dist/handlers/executionHandler.d.ts +36 -0
  78. package/dist/handlers/executionHandler.d.ts.map +1 -0
  79. package/dist/handlers/executionHandler.js +402 -0
  80. package/dist/index.d.ts +5 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js +43 -0
  83. package/dist/instrumentation.d.ts +13 -0
  84. package/dist/instrumentation.d.ts.map +1 -0
  85. package/dist/instrumentation.js +66 -0
  86. package/dist/logger.d.ts +4 -0
  87. package/dist/logger.d.ts.map +1 -0
  88. package/dist/logger.js +32 -0
  89. package/dist/middleware/api-key-auth.d.ts +22 -0
  90. package/dist/middleware/api-key-auth.d.ts.map +1 -0
  91. package/dist/middleware/api-key-auth.js +139 -0
  92. package/dist/middleware/index.d.ts +2 -0
  93. package/dist/middleware/index.d.ts.map +1 -0
  94. package/dist/middleware/index.js +1 -0
  95. package/dist/openapi.d.ts +2 -0
  96. package/dist/openapi.d.ts.map +1 -0
  97. package/dist/openapi.js +36 -0
  98. package/dist/routes/agents.d.ts +4 -0
  99. package/dist/routes/agents.d.ts.map +1 -0
  100. package/dist/routes/agents.js +155 -0
  101. package/dist/routes/chat.d.ts +4 -0
  102. package/dist/routes/chat.d.ts.map +1 -0
  103. package/dist/routes/chat.js +308 -0
  104. package/dist/routes/chatDataStream.d.ts +4 -0
  105. package/dist/routes/chatDataStream.d.ts.map +1 -0
  106. package/dist/routes/chatDataStream.js +179 -0
  107. package/dist/routes/mcp.d.ts +4 -0
  108. package/dist/routes/mcp.d.ts.map +1 -0
  109. package/dist/routes/mcp.js +500 -0
  110. package/dist/tracer.d.ts +24 -0
  111. package/dist/tracer.d.ts.map +1 -0
  112. package/dist/tracer.js +97 -0
  113. package/dist/types/chat.d.ts +25 -0
  114. package/dist/types/chat.d.ts.map +1 -0
  115. package/dist/types/chat.js +1 -0
  116. package/dist/types/execution-context.d.ts +14 -0
  117. package/dist/types/execution-context.d.ts.map +1 -0
  118. package/dist/types/execution-context.js +14 -0
  119. package/dist/utils/agent-operations.d.ts +79 -0
  120. package/dist/utils/agent-operations.d.ts.map +1 -0
  121. package/dist/utils/agent-operations.js +67 -0
  122. package/dist/utils/artifact-component-schema.d.ts +29 -0
  123. package/dist/utils/artifact-component-schema.d.ts.map +1 -0
  124. package/dist/utils/artifact-component-schema.js +119 -0
  125. package/dist/utils/artifact-parser.d.ts +71 -0
  126. package/dist/utils/artifact-parser.d.ts.map +1 -0
  127. package/dist/utils/artifact-parser.js +251 -0
  128. package/dist/utils/cleanup.d.ts +19 -0
  129. package/dist/utils/cleanup.d.ts.map +1 -0
  130. package/dist/utils/cleanup.js +66 -0
  131. package/dist/utils/data-component-schema.d.ts +6 -0
  132. package/dist/utils/data-component-schema.d.ts.map +1 -0
  133. package/dist/utils/data-component-schema.js +43 -0
  134. package/dist/utils/graph-session.d.ts +200 -0
  135. package/dist/utils/graph-session.d.ts.map +1 -0
  136. package/dist/utils/graph-session.js +1009 -0
  137. package/dist/utils/incremental-stream-parser.d.ts +57 -0
  138. package/dist/utils/incremental-stream-parser.d.ts.map +1 -0
  139. package/dist/utils/incremental-stream-parser.js +287 -0
  140. package/dist/utils/response-formatter.d.ts +27 -0
  141. package/dist/utils/response-formatter.d.ts.map +1 -0
  142. package/dist/utils/response-formatter.js +160 -0
  143. package/dist/utils/stream-helpers.d.ts +162 -0
  144. package/dist/utils/stream-helpers.d.ts.map +1 -0
  145. package/dist/utils/stream-helpers.js +385 -0
  146. package/dist/utils/stream-registry.d.ts +18 -0
  147. package/dist/utils/stream-registry.d.ts.map +1 -0
  148. package/dist/utils/stream-registry.js +33 -0
  149. package/package.json +88 -0
@@ -0,0 +1,463 @@
1
+ import { tool } from 'ai';
2
+ import jmespath from 'jmespath';
3
+ import { nanoid } from 'nanoid';
4
+ import z from 'zod';
5
+ import { getLogger } from '../logger.js';
6
+ import { graphSessionManager } from '../utils/graph-session.js';
7
+ import { parseEmbeddedJson } from './generateTaskHandler.js';
8
+ import { toolSessionManager } from './ToolSessionManager.js';
9
+ const logger = getLogger('artifactTools');
10
+ function buildKeyNestingMap(data, prefix = '', map = new Map()) {
11
+ if (typeof data === 'object' && data !== null) {
12
+ if (Array.isArray(data)) {
13
+ // For arrays, analyze the first few items
14
+ data.slice(0, 3).forEach((item, index) => {
15
+ buildKeyNestingMap(item, `${prefix}[${index}]`, map);
16
+ });
17
+ }
18
+ else {
19
+ Object.keys(data).forEach((key) => {
20
+ const fullPath = prefix ? `${prefix}.${key}` : key;
21
+ // Store all paths where this key appears
22
+ if (!map.has(key)) {
23
+ map.set(key, []);
24
+ }
25
+ map.get(key).push(fullPath);
26
+ // Recurse into nested objects
27
+ buildKeyNestingMap(data[key], fullPath, map);
28
+ });
29
+ }
30
+ }
31
+ return map;
32
+ }
33
+ function analyzeSelectorFailure(data, selector) {
34
+ const analysis = [];
35
+ const suggestions = [];
36
+ let availableKeys = [];
37
+ try {
38
+ // Build a complete map of where each key appears
39
+ const keyNestingMap = buildKeyNestingMap(data);
40
+ // Get top-level keys
41
+ if (typeof data === 'object' && data !== null) {
42
+ availableKeys = Object.keys(data);
43
+ }
44
+ // Check for quote mismatches in filters
45
+ const filterMatches = selector.match(/\[.*?\]/g);
46
+ if (filterMatches) {
47
+ filterMatches.forEach((filter) => {
48
+ const hasSingleQuote = filter.includes("'");
49
+ const hasDoubleQuote = filter.includes('"');
50
+ if (hasSingleQuote && hasDoubleQuote) {
51
+ analysis.push('MIXED QUOTES in filter');
52
+ suggestions.push('Use consistent quotes in filter conditions');
53
+ }
54
+ });
55
+ }
56
+ // Extract the target key from selector (the key we're trying to reach)
57
+ const selectorParts = selector.split('.').filter((part) => part && !part.startsWith('['));
58
+ const targetKey = selectorParts[selectorParts.length - 1]?.replace(/\[.*?\]/g, '');
59
+ // Walk the selector path to find where it breaks
60
+ let currentData = data;
61
+ let validPath = '';
62
+ let pathBroken = false;
63
+ for (let i = 0; i < selectorParts.length; i++) {
64
+ const part = selectorParts[i].replace(/\[.*?\]/g, '');
65
+ if (part && currentData && typeof currentData === 'object') {
66
+ if (!(part in currentData)) {
67
+ const pathSoFar = validPath || 'root';
68
+ analysis.push(`KEY "${part}" not found at ${pathSoFar}`);
69
+ // Use the nesting map to suggest alternative paths
70
+ if (keyNestingMap.has(part)) {
71
+ const allPaths = keyNestingMap.get(part);
72
+ const relevantPaths = allPaths.filter((path) => path.includes(validPath) || validPath === '');
73
+ if (relevantPaths.length > 0) {
74
+ suggestions.push(`"${part}" exists at: ${relevantPaths.slice(0, 3).join(', ')}`);
75
+ }
76
+ }
77
+ pathBroken = true;
78
+ break;
79
+ }
80
+ currentData = currentData[part];
81
+ validPath = validPath ? `${validPath}.${part}` : part;
82
+ }
83
+ }
84
+ // If path is valid but selector still failed, it's likely a filter issue with nested data
85
+ if (!pathBroken && targetKey && keyNestingMap.has(targetKey)) {
86
+ analysis.push('PATH VALID BUT FILTER FAILED');
87
+ const allPaths = keyNestingMap.get(targetKey);
88
+ const deeperPaths = allPaths.filter((path) => path.length > selector.replace(/\[.*?\]/g, '').length);
89
+ if (deeperPaths.length > 0) {
90
+ suggestions.push(`"${targetKey}" also found deeper at: ${deeperPaths.slice(0, 3).join(', ')}`);
91
+ suggestions.push('Try a deeper path or check filter values');
92
+ }
93
+ }
94
+ if (analysis.length === 0) {
95
+ analysis.push('UNKNOWN SELECTOR ISSUE');
96
+ }
97
+ }
98
+ catch (debugError) {
99
+ analysis.push('SYNTAX ERROR');
100
+ suggestions.push('Check JMESPath syntax');
101
+ }
102
+ return { analysis, suggestions, availableKeys };
103
+ }
104
+ function createPropSelectorsSchema(artifactComponents) {
105
+ if (!artifactComponents || artifactComponents.length === 0) {
106
+ return z
107
+ .record(z.string(), z.string())
108
+ .describe('Prop selectors mapping schema properties to JMESPath expressions relative to base selector');
109
+ }
110
+ // Create a union of all possible prop selector schemas based on artifact components
111
+ const propSelectorSchemas = artifactComponents.map((ac) => {
112
+ const props = ac.summaryProps ||
113
+ ac.fullProps ||
114
+ {};
115
+ // Create schema object for each property in the artifact component
116
+ const propSchema = {};
117
+ // Add properties from summaryProps schema
118
+ if (ac.summaryProps && typeof ac.summaryProps === 'object') {
119
+ const summaryProps = ac.summaryProps;
120
+ if (summaryProps.properties) {
121
+ Object.entries(summaryProps.properties).forEach(([propName, propDef]) => {
122
+ const propDescription = propDef?.description || propDef?.title || `${propName} property`;
123
+ propSchema[propName] = z
124
+ .string()
125
+ .describe(`JMESPath selector for ${propName} (${propDescription}) - summary version, relative to base selector`);
126
+ });
127
+ }
128
+ }
129
+ // Add properties from fullProps schema
130
+ if (ac.fullProps && typeof ac.fullProps === 'object') {
131
+ const fullProps = ac.fullProps;
132
+ if (fullProps.properties) {
133
+ Object.entries(fullProps.properties).forEach(([propName, propDef]) => {
134
+ // Don't overwrite if already exists from summary
135
+ if (!propSchema[propName]) {
136
+ const propDescription = propDef?.description || propDef?.title || `${propName} property`;
137
+ propSchema[propName] = z
138
+ .string()
139
+ .describe(`JMESPath selector for ${propName} (${propDescription}) - full version, relative to base selector`);
140
+ }
141
+ });
142
+ }
143
+ }
144
+ return z.object(propSchema).describe(`Prop selectors for ${ac.name} artifact`);
145
+ });
146
+ // Return union of all prop selector schemas or fallback to generic record
147
+ if (propSelectorSchemas.length === 1) {
148
+ return propSelectorSchemas[0];
149
+ }
150
+ else if (propSelectorSchemas.length > 1) {
151
+ return z.union(propSelectorSchemas);
152
+ }
153
+ return z
154
+ .record(z.string(), z.string())
155
+ .describe('Prop selectors mapping schema properties to JMESPath expressions relative to base selector');
156
+ }
157
+ function createInputSchema(artifactComponents) {
158
+ const baseSchema = z.object({
159
+ toolCallId: z
160
+ .string()
161
+ .describe('EXACT toolCallId from a previous tool execution - copy it exactly from the tool call result. NEVER invent or make up tool call IDs.'),
162
+ baseSelector: z
163
+ .string()
164
+ .describe('JMESPath selector to get to the main data array/object. ALWAYS start with "result." Example: "result.content[?type==\'text\']"'),
165
+ propSelectors: createPropSelectorsSchema(artifactComponents),
166
+ });
167
+ // If no artifact components, return base schema
168
+ if (!artifactComponents || artifactComponents.length === 0) {
169
+ return baseSchema;
170
+ }
171
+ // Add artifactType selection based on available artifact components
172
+ return baseSchema.extend({
173
+ artifactType: z
174
+ .enum(artifactComponents.map((ac) => ac.name))
175
+ .describe(`Type of artifact to create. Available types: ${artifactComponents.map((ac) => ac.name).join(', ')}`),
176
+ });
177
+ }
178
+ export function createSaveToolResultTool(sessionId, streamRequestId, // For GraphSession recording
179
+ agentId, artifactComponents) {
180
+ const inputSchema = createInputSchema(artifactComponents);
181
+ // Create available types with descriptions for better context
182
+ const availableTypesWithDescriptions = artifactComponents?.length
183
+ ? artifactComponents
184
+ .map((ac) => `- ${ac.name}: ${ac.description || 'No description available'}`)
185
+ .join('\n')
186
+ : 'Generic artifacts';
187
+ return tool({
188
+ description: `Save tool results as structured artifacts. Each artifact should represent ONE SPECIFIC, IMPORTANT, and UNIQUE document or data item.
189
+
190
+ AVAILABLE ARTIFACT TYPES:
191
+ ${availableTypesWithDescriptions}
192
+
193
+ 🚨 FUNDAMENTAL RULE: ONE ARTIFACT = ONE SEPARATE DATA COMPONENT 🚨
194
+
195
+ Each artifact you save becomes a SEPARATE DATA COMPONENT in the structured response:
196
+ ✅ A SINGLE, SPECIFIC document (e.g., one specific API endpoint, one specific person's profile, one specific error)
197
+ ✅ IMPORTANT and directly relevant to the user's question
198
+ ✅ UNIQUE with distinct value from other artifacts
199
+ ✅ RENDERED AS INDIVIDUAL DATA COMPONENT in the UI
200
+
201
+ ❌ DO NOT save multiple different items in one artifact unless they are EXTREMELY SIMILAR
202
+ ❌ DO NOT batch unrelated items together - each item becomes its own data component
203
+ ❌ DO NOT save generic collections - break them into individual data components
204
+
205
+ 🎯 STRUCTURED DATA COMPONENT PRINCIPLE:
206
+ Each artifact save creates ONE data component that will be rendered separately in the UI. If you have 5 important items, save them as 5 separate artifacts to create 5 separate data components for better user experience.
207
+
208
+ THINK: "What is the ONE most important piece of information here that deserves its own data component?"
209
+
210
+ EXAMPLES OF GOOD INDIVIDUAL ARTIFACTS (SEPARATE DATA COMPONENTS):
211
+ - Nick Gomez's founder profile (specific person) → Individual data component
212
+ - The /users/create API endpoint documentation (specific endpoint) → Individual data component
213
+ - Error message for authentication failure (specific error type) → Individual data component
214
+ - Configuration for Redis caching (specific config topic) → Individual data component
215
+
216
+ EXAMPLES OF BAD BATCHING:
217
+ ❌ "All team members" → Should be separate artifacts for each important member (separate data components)
218
+ ❌ "All API endpoints" → Should be separate artifacts for each distinct endpoint (separate data components)
219
+ ❌ "All error types" → Should be separate artifacts for each error category (separate data components)
220
+
221
+ USAGE PATTERN:
222
+ 1. baseSelector: Navigate through nested structures to target ONE SPECIFIC item
223
+ - Navigate through all necessary levels: "result.data.items.nested[?condition]"
224
+ - Handle nested structures properly: "result.content.content[?field1=='value']" is fine if that's the structure
225
+ - Use [?condition] filtering to get exactly the item you want
226
+ - Example: "result.items[?field_a=='target_value' && field_b=='specific_type']"
227
+ - NOT: "result.items[*]" (too broad, gets everything)
228
+
229
+ 2. propSelectors: Extract properties relative to your selected item
230
+ - Always relative to the single item that baseSelector returns
231
+ - Simple paths from that item: { prop1: "field_x", prop2: "nested.field_y", prop3: "deep.nested.field_z" }
232
+ - The tool handles array iteration - your selectors work on individual items
233
+
234
+ 3. Result: ONE artifact representing ONE important, unique item → ONE data component
235
+
236
+ 💡 HANDLING NESTED STRUCTURES:
237
+ - Navigate as deep as needed: "result.data.items.content.documents[?condition]" is fine
238
+ - Focus on getting to the right level with baseSelector, then keep propSelectors simple
239
+ - Test your baseSelector: Does it return exactly the items you want?
240
+
241
+ ⚠️ STRICT SELECTIVITY RULES FOR DATA COMPONENTS:
242
+ - ALWAYS ask: "Is this ONE specific, important thing that deserves its own data component?"
243
+ - If the answer is no, don't save it or find a more specific selector
244
+ - Multiple similar items = Multiple separate artifact saves (use the tool multiple times) → Multiple data components
245
+ - Each artifact should be independently valuable and uniquely identifiable → Each data component stands alone
246
+ - BETTER to save 3 individual, specific artifacts (3 data components) than 1 generic collection (1 data component)
247
+
248
+ 🔄 MULTIPLE ARTIFACTS = MULTIPLE DATA COMPONENTS:
249
+ Remember: Each time you call this tool, you create a separate data component. Call it multiple times for multiple items to create a rich, structured response with individual data components for each important piece of information.`,
250
+ inputSchema,
251
+ execute: async ({ toolCallId, baseSelector, propSelectors, ...rest }, context) => {
252
+ const artifactType = 'artifactType' in rest ? rest.artifactType : undefined;
253
+ if (!sessionId) {
254
+ logger.warn({ toolCallId }, 'No session ID provided to save_tool_result');
255
+ return {
256
+ saved: false,
257
+ error: `[toolCallId: ${toolCallId}] No session context available`,
258
+ artifactIds: [],
259
+ warnings: [],
260
+ };
261
+ }
262
+ // Get the tool result from the session
263
+ const toolResult = toolSessionManager.getToolResult(sessionId, toolCallId);
264
+ if (!toolResult) {
265
+ logger.warn({ toolCallId, sessionId }, 'Tool result not found in session');
266
+ return {
267
+ saved: false,
268
+ error: `[toolCallId: ${toolCallId}] Tool result not found`,
269
+ artifactIds: [],
270
+ warnings: [],
271
+ };
272
+ }
273
+ try {
274
+ const parsedResult = parseEmbeddedJson(toolResult);
275
+ // Use baseSelector to get to the main data
276
+ const baseData = jmespath.search(parsedResult, baseSelector);
277
+ if (!baseData || (Array.isArray(baseData) && baseData.length === 0)) {
278
+ // Enhanced debugging for failed selectors
279
+ const debugInfo = analyzeSelectorFailure(parsedResult, baseSelector);
280
+ logger.warn({
281
+ baseSelector,
282
+ toolCallId,
283
+ analysis: debugInfo.analysis,
284
+ suggestions: debugInfo.suggestions,
285
+ availableKeys: debugInfo.availableKeys,
286
+ }, 'Base selector returned no results - selector may be incorrect');
287
+ const errorMessage = [
288
+ `[toolCallId: ${toolCallId}] Base selector "${baseSelector}" returned no results.`,
289
+ '',
290
+ '🔍 DETECTED ISSUES: ' + debugInfo.analysis.join(' | '),
291
+ '',
292
+ '💡 SUGGESTIONS:',
293
+ ...debugInfo.suggestions.map((s) => ` • ${s}`),
294
+ '',
295
+ '📊 AVAILABLE TOP-LEVEL KEYS: ' + debugInfo.availableKeys.join(', '),
296
+ ].join('\n');
297
+ return {
298
+ saved: false,
299
+ error: errorMessage,
300
+ artifactIds: [],
301
+ warnings: [],
302
+ };
303
+ }
304
+ // Helper function to extract properties from items based on schema
305
+ const extractProps = (items, schema, context = 'default') => {
306
+ const failedSelectors = [];
307
+ const extractedItems = items.map((item, index) => {
308
+ const extractedItem = {};
309
+ const schemaProperties = schema?.properties || {};
310
+ for (const [propName, propSchema] of Object.entries(schemaProperties)) {
311
+ const propSelector = propSelectors[propName];
312
+ if (propSelector) {
313
+ try {
314
+ const propValue = jmespath.search(item, propSelector);
315
+ if (propValue !== null && propValue !== undefined) {
316
+ extractedItem[propName] = propValue;
317
+ }
318
+ else {
319
+ // PropSelector didn't match anything - try fallback to direct property access
320
+ const fallbackValue = item[propName];
321
+ if (fallbackValue !== null && fallbackValue !== undefined) {
322
+ extractedItem[propName] = fallbackValue;
323
+ logger.info({ propName, propSelector, context }, `PropSelector failed, used fallback direct property access`);
324
+ }
325
+ else {
326
+ failedSelectors.push(`${propName}: "${propSelector}"`);
327
+ }
328
+ }
329
+ }
330
+ catch (error) {
331
+ // JMESPath syntax error - try fallback
332
+ const fallbackValue = item[propName];
333
+ if (fallbackValue !== null && fallbackValue !== undefined) {
334
+ extractedItem[propName] = fallbackValue;
335
+ logger.warn({ propName, propSelector, context, error: error.message }, `PropSelector syntax error, used fallback direct property access`);
336
+ }
337
+ else {
338
+ failedSelectors.push(`${propName}: "${propSelector}" (syntax error)`);
339
+ }
340
+ }
341
+ }
342
+ }
343
+ return extractedItem;
344
+ });
345
+ // Return both the extracted items and any failed selectors for error reporting
346
+ return { extractedItems, failedSelectors };
347
+ };
348
+ // Find the matching artifact component
349
+ const targetArtifactComponent = artifactComponents?.find((ac) => ac.name === artifactType);
350
+ // Normalize baseData to always be an array
351
+ const dataItems = Array.isArray(baseData) ? baseData : [baseData];
352
+ // Extract data based on dataComponent configuration
353
+ let summaryData;
354
+ let fullData;
355
+ const allFailedSelectors = [];
356
+ if (targetArtifactComponent?.summaryProps || targetArtifactComponent?.fullProps) {
357
+ // ArtifactComponent format - summaryProps and fullProps are direct properties
358
+ if (targetArtifactComponent.summaryProps) {
359
+ const summaryResult = extractProps(dataItems, targetArtifactComponent.summaryProps, 'summary');
360
+ summaryData = summaryResult.extractedItems;
361
+ allFailedSelectors.push(...summaryResult.failedSelectors.map((s) => `summary.${s}`));
362
+ }
363
+ else {
364
+ summaryData = [];
365
+ }
366
+ if (targetArtifactComponent.fullProps) {
367
+ const fullResult = extractProps(dataItems, targetArtifactComponent.fullProps, 'full');
368
+ fullData = fullResult.extractedItems;
369
+ allFailedSelectors.push(...fullResult.failedSelectors.map((s) => `full.${s}`));
370
+ }
371
+ else {
372
+ fullData = [];
373
+ }
374
+ }
375
+ else {
376
+ // Backward compatibility: use all propSelectors (current behavior)
377
+ const allPropsSchema = {
378
+ properties: Object.keys(propSelectors).reduce((acc, key) => {
379
+ acc[key] = {}; // Schema doesn't matter for this case
380
+ return acc;
381
+ }, {}),
382
+ };
383
+ const structuredResult = extractProps(dataItems, allPropsSchema, 'structured');
384
+ summaryData = structuredResult.extractedItems;
385
+ fullData = structuredResult.extractedItems;
386
+ allFailedSelectors.push(...structuredResult.failedSelectors);
387
+ }
388
+ // If there are failed selectors, include them in the response as warnings
389
+ const warnings = allFailedSelectors.length > 0
390
+ ? [
391
+ `[toolCallId: ${toolCallId}] [artifactType: ${artifactType || 'unknown'}] Some propSelectors failed: ${allFailedSelectors.join(', ')}. Used fallback direct property access where possible.`,
392
+ ]
393
+ : [];
394
+ // Prepare artifact data for later processing (not saving immediately)
395
+ const artifactDataItems = dataItems.map((item, index) => ({
396
+ artifactId: nanoid(),
397
+ summaryData: summaryData[index] || {},
398
+ fullData: fullData[index] || {},
399
+ metadata: {
400
+ toolName: toolResult.toolName,
401
+ toolCallId: toolResult.toolCallId,
402
+ baseSelector,
403
+ propSelectors,
404
+ artifactType,
405
+ sessionId: sessionId,
406
+ itemIndex: index,
407
+ totalItems: dataItems.length,
408
+ },
409
+ }));
410
+ const session = toolSessionManager.getSession(sessionId);
411
+ const taskId = session?.taskId;
412
+ // Record artifact preparation events in GraphSession for out-of-band processing
413
+ // The actual saving will happen after name/description generation
414
+ if (streamRequestId && agentId && session) {
415
+ artifactDataItems.forEach((artifactData, index) => {
416
+ // Record event that will trigger name/description generation
417
+ graphSessionManager.recordEvent(streamRequestId, 'artifact_saved', agentId, {
418
+ artifactId: artifactData.artifactId,
419
+ taskId: taskId || 'unknown',
420
+ artifactType: artifactType || 'unknown',
421
+ summaryProps: artifactData.summaryData,
422
+ fullProps: artifactData.fullData,
423
+ metadata: artifactData.metadata,
424
+ // Session info needed for saving to ledger
425
+ tenantId: session.tenantId,
426
+ projectId: session.projectId,
427
+ contextId: session.contextId,
428
+ // Mark as pending - needs name/description generation
429
+ pendingGeneration: true,
430
+ });
431
+ });
432
+ }
433
+ // Build artifacts object with only the essential data
434
+ const artifacts = artifactDataItems.reduce((acc, artifactData, index) => {
435
+ acc[`${artifactData.artifactId}:${taskId}`] = {
436
+ artifactId: artifactData.artifactId,
437
+ artifactType,
438
+ taskId: taskId,
439
+ summaryData: artifactData.summaryData,
440
+ };
441
+ return acc;
442
+ }, {});
443
+ return {
444
+ saved: true,
445
+ artifacts: Object.values(artifacts).map((a) => ({
446
+ artifactId: a.artifactId,
447
+ taskId: a.taskId,
448
+ summaryData: a.summaryData,
449
+ })),
450
+ warnings,
451
+ };
452
+ }
453
+ catch (error) {
454
+ logger.error({ error, toolCallId, sessionId }, 'Error processing save_tool_result');
455
+ return {
456
+ saved: false,
457
+ error: `[toolCallId: ${toolCallId}] ${error instanceof Error ? error.message : 'Unknown error'}`,
458
+ warnings: [],
459
+ };
460
+ }
461
+ },
462
+ });
463
+ }
@@ -0,0 +1,41 @@
1
+ import type { A2ATask, A2ATaskResult } from '../a2a/types.js';
2
+ import { type AgentApiSelect, type AgentConversationHistoryConfig } from '@inkeep/agents-core';
3
+ /** Turn any string value that is valid JSON into an object/array (in place). */
4
+ export declare function parseEmbeddedJson<T>(data: T): T;
5
+ /**
6
+ * Serializable configuration for creating task handlers
7
+ */
8
+ export interface TaskHandlerConfig {
9
+ tenantId: string;
10
+ projectId: string;
11
+ graphId: string;
12
+ agentId: string;
13
+ agentSchema: AgentApiSelect;
14
+ name: string;
15
+ baseUrl: string;
16
+ apiKey?: string;
17
+ description?: string;
18
+ contextConfigId?: string;
19
+ conversationHistoryConfig?: AgentConversationHistoryConfig;
20
+ }
21
+ export declare const createTaskHandler: (config: TaskHandlerConfig) => (task: A2ATask) => Promise<A2ATaskResult>;
22
+ /**
23
+ * Serializes a TaskHandlerConfig to JSON
24
+ */
25
+ export declare const serializeTaskHandlerConfig: (config: TaskHandlerConfig) => string;
26
+ /**
27
+ * Deserializes a TaskHandlerConfig from JSON
28
+ */
29
+ export declare const deserializeTaskHandlerConfig: (configJson: string) => TaskHandlerConfig;
30
+ /**
31
+ * Creates a task handler configuration from agent data
32
+ */
33
+ export declare const createTaskHandlerConfig: (params: {
34
+ tenantId: string;
35
+ projectId: string;
36
+ graphId: string;
37
+ agentId: string;
38
+ baseUrl: string;
39
+ apiKey?: string;
40
+ }) => Promise<TaskHandlerConfig>;
41
+ //# sourceMappingURL=generateTaskHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateTaskHandler.d.ts","sourceRoot":"","sources":["../../src/agents/generateTaskHandler.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,8BAA8B,EAQpC,MAAM,qBAAqB,CAAC;AAM7B,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,CAS/C;AAID;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,cAAc,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yBAAyB,CAAC,EAAE,8BAA8B,CAAC;CAC5D;AAED,eAAO,MAAM,iBAAiB,GAAI,QAAQ,iBAAiB,MAC3C,MAAM,OAAO,KAAG,OAAO,CAAC,aAAa,CAgUpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,GAAI,QAAQ,iBAAiB,KAAG,MAEtE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,4BAA4B,GAAI,YAAY,MAAM,KAAG,iBAEjE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAU,QAAQ;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,KAAG,OAAO,CAAC,iBAAiB,CAgD5B,CAAC"}