@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,21 @@
1
+ import type { McpTool } from '@inkeep/agents-core';
2
+ import type { SystemPromptV1, ToolData, VersionConfig } from '../types.js';
3
+ export declare class V1Config implements VersionConfig<SystemPromptV1> {
4
+ readonly templateFiles: string[];
5
+ static convertMcpToolsToToolData(mcpTools: McpTool[] | undefined): ToolData[];
6
+ private isToolDataArray;
7
+ assemble(templates: Map<string, string>, config: SystemPromptV1): string;
8
+ private generateGraphContextSection;
9
+ private generateThinkingPreparationSection;
10
+ private generateTransferInstructions;
11
+ private generateDelegationInstructions;
12
+ private getArtifactReferencingRules;
13
+ private generateArtifactsSection;
14
+ private generateArtifactXml;
15
+ private generateToolsSection;
16
+ private generateToolXml;
17
+ private generateDataComponentsSection;
18
+ private generateDataComponentXml;
19
+ private generateParametersXml;
20
+ }
21
+ //# sourceMappingURL=V1Config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"V1Config.d.ts","sourceRoot":"","sources":["../../../src/agents/versions/V1Config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA0B,OAAO,EAAY,MAAM,qBAAqB,CAAC;AACrF,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE3E,qBAAa,QAAS,YAAW,aAAa,CAAC,cAAc,CAAC;IAC5D,QAAQ,CAAC,aAAa,WAMpB;IAEF,MAAM,CAAC,yBAAyB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,SAAS,GAAG,QAAQ,EAAE;IAoB7E,OAAO,CAAC,eAAe;IAOvB,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM;IAwDxE,OAAO,CAAC,2BAA2B;IAWnC,OAAO,CAAC,kCAAkC;IAgB1C,OAAO,CAAC,4BAA4B;IAQpC,OAAO,CAAC,8BAA8B;IAQtC,OAAO,CAAC,2BAA2B;IAqEnC,OAAO,CAAC,wBAAwB;IA4BhC,OAAO,CAAC,mBAAmB;IAwB3B,OAAO,CAAC,oBAAoB;IAW5B,OAAO,CAAC,eAAe;IA0BvB,OAAO,CAAC,6BAA6B;IAiCrC,OAAO,CAAC,wBAAwB;IAyBhC,OAAO,CAAC,qBAAqB;CAqB9B"}
@@ -0,0 +1,285 @@
1
+ export class V1Config {
2
+ templateFiles = [
3
+ 'system-prompt.xml',
4
+ 'tool.xml',
5
+ 'data-component.xml',
6
+ 'artifact.xml',
7
+ 'thinking-preparation.xml',
8
+ ];
9
+ static convertMcpToolsToToolData(mcpTools) {
10
+ if (!mcpTools || mcpTools.length === 0) {
11
+ return [];
12
+ }
13
+ const toolData = [];
14
+ for (const mcpTool of mcpTools) {
15
+ if (mcpTool.availableTools) {
16
+ for (const toolDef of mcpTool.availableTools) {
17
+ toolData.push({
18
+ name: toolDef.name,
19
+ description: toolDef.description || 'No description available',
20
+ inputSchema: toolDef.inputSchema || {},
21
+ usageGuidelines: `Use this tool from ${mcpTool.name} server when appropriate.`,
22
+ });
23
+ }
24
+ }
25
+ }
26
+ return toolData;
27
+ }
28
+ isToolDataArray(tools) {
29
+ if (!tools || tools.length === 0)
30
+ return true; // Default to ToolData[] for empty arrays
31
+ // Check if the first item has properties of ToolData vs McpTool
32
+ const firstItem = tools[0];
33
+ return 'usageGuidelines' in firstItem && !('config' in firstItem);
34
+ }
35
+ assemble(templates, config) {
36
+ const systemPromptTemplate = templates.get('system-prompt');
37
+ if (!systemPromptTemplate) {
38
+ throw new Error('System prompt template not loaded');
39
+ }
40
+ let systemPrompt = systemPromptTemplate;
41
+ // Replace core prompt
42
+ systemPrompt = systemPrompt.replace('{{CORE_INSTRUCTIONS}}', config.corePrompt);
43
+ // Replace graph context section
44
+ const graphContextSection = this.generateGraphContextSection(config.graphPrompt);
45
+ systemPrompt = systemPrompt.replace('{{GRAPH_CONTEXT_SECTION}}', graphContextSection);
46
+ // Handle both McpTool[] and ToolData[] formats
47
+ const toolData = this.isToolDataArray(config.tools)
48
+ ? config.tools
49
+ : V1Config.convertMcpToolsToToolData(config.tools);
50
+ const hasDataComponents = config.dataComponents && config.dataComponents.length > 0;
51
+ const artifactsSection = this.generateArtifactsSection(templates, config.artifacts, hasDataComponents);
52
+ systemPrompt = systemPrompt.replace('{{ARTIFACTS_SECTION}}', artifactsSection);
53
+ const toolsSection = this.generateToolsSection(templates, toolData);
54
+ systemPrompt = systemPrompt.replace('{{TOOLS_SECTION}}', toolsSection);
55
+ const dataComponentsSection = this.generateDataComponentsSection(templates, config.dataComponents);
56
+ systemPrompt = systemPrompt.replace('{{DATA_COMPONENTS_SECTION}}', dataComponentsSection);
57
+ const thinkingPreparationSection = this.generateThinkingPreparationSection(templates, config.isThinkingPreparation);
58
+ systemPrompt = systemPrompt.replace('{{THINKING_PREPARATION_INSTRUCTIONS}}', thinkingPreparationSection);
59
+ // Generate agent relation instructions based on configuration
60
+ const transferSection = this.generateTransferInstructions(config.hasTransferRelations);
61
+ systemPrompt = systemPrompt.replace('{{TRANSFER_INSTRUCTIONS}}', transferSection);
62
+ const delegationSection = this.generateDelegationInstructions(config.hasDelegateRelations);
63
+ systemPrompt = systemPrompt.replace('{{DELEGATION_INSTRUCTIONS}}', delegationSection);
64
+ return systemPrompt;
65
+ }
66
+ generateGraphContextSection(graphPrompt) {
67
+ if (!graphPrompt) {
68
+ return '';
69
+ }
70
+ return `
71
+ <graph_context>
72
+ ${graphPrompt}
73
+ </graph_context>`;
74
+ }
75
+ generateThinkingPreparationSection(templates, isThinkingPreparation) {
76
+ if (!isThinkingPreparation) {
77
+ return '';
78
+ }
79
+ const thinkingPreparationTemplate = templates.get('thinking-preparation');
80
+ if (!thinkingPreparationTemplate) {
81
+ throw new Error('Thinking preparation template not loaded');
82
+ }
83
+ return thinkingPreparationTemplate;
84
+ }
85
+ generateTransferInstructions(hasTransferRelations) {
86
+ if (!hasTransferRelations) {
87
+ return '';
88
+ }
89
+ return '- A transfer entails you passing control of the conversation to another agent that may be better suited to handle the task at hand.';
90
+ }
91
+ generateDelegationInstructions(hasDelegateRelations) {
92
+ if (!hasDelegateRelations) {
93
+ return '';
94
+ }
95
+ return '- A delegation means asking another agent to complete a specific task and return the result to you.';
96
+ }
97
+ getArtifactReferencingRules(hasDataComponents = false) {
98
+ if (hasDataComponents) {
99
+ return `CRITICAL ARTIFACT REFERENCING RULES - MUST ALWAYS FOLLOW:
100
+
101
+ ***GROUNDING REQUIREMENT - ABSOLUTELY MANDATORY***:
102
+ - EVERY response MUST be GROUNDED in artifacts when information comes from sources
103
+ - ALWAYS try to reference artifacts - this is ESSENTIAL for credible, traceable responses
104
+ - You can NEVER overuse artifact references but you can very easily underuse them
105
+ - Artifact references provide the foundation of trust and verifiability for all information
106
+
107
+ 🚨 INDIVIDUAL ARTIFACT PRINCIPLE 🚨:
108
+ - Each artifact represents ONE SPECIFIC, IMPORTANT, and UNIQUE document or data item
109
+ - Reference artifacts individually by their specific relevance
110
+ - Multiple separate artifacts are better than one generic collection
111
+ - Think: "What specific document/item am I referencing here?"
112
+
113
+ FOR STRUCTURED DATA COMPONENT RESPONSES:
114
+
115
+ 🚨 CRITICAL: COPY EXACT IDs FROM TOOL OUTPUT 🚨
116
+
117
+ 1. MIX Artifact components throughout your dataComponents array - NEVER group them at the end
118
+ 2. PATTERN: Present information → Immediately follow with supporting Artifact → Next information → Next Artifact
119
+ 3. **LOOK AT THE TOOL OUTPUT**: Find the save_tool_result output and copy the EXACT artifact_id and task_id
120
+ 4. **NEVER MAKE UP IDs**: Do not invent, guess, or modify the IDs - copy them EXACTLY as shown in tool results
121
+ 5. ALL artifact references MUST use exact artifact_id and task_id - NEVER reference by name or description
122
+ 6. Use Artifact components liberally and frequently - INTERSPERSE them after EVERY claim or fact from sources
123
+ 7. Reference individual, specific artifacts that directly support each adjacent piece of information
124
+
125
+ MANDATORY FORMAT WITH EXACT IDs FROM TOOL OUTPUT:
126
+ - Data Component: {"artifact_id": "art_founder_abc123", "task_id": "task_search_def456"}
127
+ - NEVER: {"artifact_name": "some name"} or {"description": "some description"}
128
+ - NEVER: {"artifact_id": "made_up_id"} - ALWAYS copy from tool output
129
+
130
+ ⚠️ WRONG IDs = BROKEN REFERENCES! Always copy from save_tool_result output! ⚠️`;
131
+ }
132
+ else {
133
+ return `CRITICAL ARTIFACT REFERENCING RULES - MUST ALWAYS FOLLOW:
134
+
135
+ ***GROUNDING REQUIREMENT - ABSOLUTELY MANDATORY***:
136
+ - EVERY response MUST be GROUNDED in artifacts when information comes from sources
137
+ - ALWAYS try to reference artifacts - this is ESSENTIAL for credible, traceable responses
138
+ - You can NEVER overuse artifact references but you can very easily underuse them
139
+ - Artifact references provide the foundation of trust and verifiability for all information
140
+
141
+ 🚨 INDIVIDUAL ARTIFACT PRINCIPLE 🚨:
142
+ - Each artifact represents ONE SPECIFIC, IMPORTANT, and UNIQUE document or data item
143
+ - Reference artifacts individually by their specific relevance
144
+ - Multiple separate artifacts are better than one generic collection
145
+ - Think: "What specific document/item am I referencing here?"
146
+
147
+ FOR PLAIN TEXT RESPONSES (when data components are NOT available):
148
+
149
+ 🚨 CRITICAL: COPY EXACT IDs FROM TOOL OUTPUT 🚨
150
+
151
+ 1. When referencing ANY artifact in flowing text, ALWAYS use this exact format: <artifact:ref id="{{artifact_id}}" task="{{task_id}}" />
152
+ 2. **LOOK AT THE TOOL OUTPUT**: Find the save_tool_result output and copy the EXACT artifact_id and task_id
153
+ 3. **NEVER MAKE UP IDs**: Do not invent, guess, or modify the IDs - copy them EXACTLY as shown in tool results
154
+ 4. NEVER reference artifacts by name or description alone - IDs are MANDATORY
155
+ 5. This format is MANDATORY for text content, delegation messages, and all responses
156
+ 6. These markers are automatically converted to interactive references
157
+ 7. Reference individual, specific artifacts that directly support each piece of information
158
+
159
+ EXAMPLES WITH EXACT IDs FROM TOOL OUTPUT:
160
+ - Plain Text: "Based on the Nick Gomez profile <artifact:ref id="art_founder_abc123" task="task_search_def456" /> you can..."
161
+ - Delegation: "Delegating to agent with founder information <artifact:ref id="art_profile_xyz789" task="task_analysis_uvw012" />"
162
+
163
+ ⚠️ WRONG IDs = BROKEN REFERENCES! Always copy from save_tool_result output! ⚠️`;
164
+ }
165
+ }
166
+ generateArtifactsSection(templates, artifacts, hasDataComponents = false) {
167
+ const rules = this.getArtifactReferencingRules(hasDataComponents);
168
+ if (artifacts.length === 0) {
169
+ return `<available_artifacts description="No artifacts are currently available, but you may create them during execution.
170
+
171
+ ${rules}
172
+
173
+ "></available_artifacts>`;
174
+ }
175
+ const artifactsXml = artifacts
176
+ .map((artifact) => this.generateArtifactXml(templates, artifact))
177
+ .join('\n ');
178
+ return `<available_artifacts description="These are the artifacts available for you to use in generating responses.
179
+
180
+ ${rules}
181
+
182
+ ">
183
+ ${artifactsXml}
184
+ </available_artifacts>`;
185
+ }
186
+ generateArtifactXml(templates, artifact) {
187
+ const artifactTemplate = templates.get('artifact');
188
+ if (!artifactTemplate) {
189
+ throw new Error('Artifact template not loaded');
190
+ }
191
+ let artifactXml = artifactTemplate;
192
+ // Extract summary data from artifact parts for context
193
+ const summaryData = artifact.parts?.map((part) => part.data?.summary).filter(Boolean) || [];
194
+ const artifactSummary = summaryData.length > 0 ? JSON.stringify(summaryData, null, 2) : 'No summary data available';
195
+ // Replace artifact variables
196
+ artifactXml = artifactXml.replace('{{ARTIFACT_NAME}}', artifact.name || '');
197
+ artifactXml = artifactXml.replace('{{ARTIFACT_DESCRIPTION}}', artifact.description || '');
198
+ artifactXml = artifactXml.replace('{{TASK_ID}}', artifact.taskId || '');
199
+ artifactXml = artifactXml.replace('{{ARTIFACT_ID}}', artifact.artifactId || '');
200
+ artifactXml = artifactXml.replace('{{ARTIFACT_SUMMARY}}', artifactSummary);
201
+ return artifactXml;
202
+ }
203
+ generateToolsSection(templates, tools) {
204
+ if (tools.length === 0) {
205
+ return '<available_tools description="No tools are currently available"></available_tools>';
206
+ }
207
+ const toolsXml = tools.map((tool) => this.generateToolXml(templates, tool)).join('\n ');
208
+ return `<available_tools description="These are the tools available for you to use to accomplish tasks">
209
+ ${toolsXml}
210
+ </available_tools>`;
211
+ }
212
+ generateToolXml(templates, tool) {
213
+ const toolTemplate = templates.get('tool');
214
+ if (!toolTemplate) {
215
+ throw new Error('Tool template not loaded');
216
+ }
217
+ let toolXml = toolTemplate;
218
+ // Replace tool variables
219
+ toolXml = toolXml.replace('{{TOOL_NAME}}', tool.name);
220
+ toolXml = toolXml.replace('{{TOOL_DESCRIPTION}}', tool.description || 'No description available');
221
+ toolXml = toolXml.replace('{{TOOL_USAGE_GUIDELINES}}', tool.usageGuidelines || 'Use this tool when appropriate.');
222
+ // Convert parameters to XML format
223
+ const parametersXml = this.generateParametersXml(tool.inputSchema);
224
+ toolXml = toolXml.replace('{{TOOL_PARAMETERS_SCHEMA}}', parametersXml);
225
+ return toolXml;
226
+ }
227
+ generateDataComponentsSection(templates, dataComponents) {
228
+ if (dataComponents.length === 0) {
229
+ return '';
230
+ }
231
+ const dataComponentsXml = dataComponents
232
+ .map((dataComponent) => this.generateDataComponentXml(templates, dataComponent))
233
+ .join('\n ');
234
+ return `<available_data_components description="These are the data components available for you to use in generating responses. Each component represents a single structured piece of information. You can create multiple instances of the same component type when needed.
235
+
236
+ ***MANDATORY JSON RESPONSE FORMAT - ABSOLUTELY CRITICAL***:
237
+ - WHEN DATA COMPONENTS ARE AVAILABLE, YOU MUST RESPOND IN JSON FORMAT ONLY
238
+ - DO NOT respond with plain text when data components are defined
239
+ - YOUR RESPONSE MUST BE STRUCTURED JSON WITH dataComponents ARRAY
240
+ - THIS IS NON-NEGOTIABLE - JSON FORMAT IS REQUIRED
241
+
242
+ CRITICAL JSON FORMATTING RULES - MUST FOLLOW EXACTLY:
243
+ 1. Each data component must include id, name, and props fields
244
+ 2. The id and name should match the exact component definition
245
+ 3. The props field contains the actual component data using exact property names from the schema
246
+ 4. NEVER omit the id and name fields
247
+
248
+ CORRECT: [{\"id\": \"component1\", \"name\": \"Component1\", \"props\": {\"field1\": \"value1\", \"field2\": \"value2\"}}, {\"id\": \"component2\", \"name\": \"Component2\", \"props\": {\"field3\": \"value3\"}}]
249
+ WRONG: [{\"field1\": \"value1\", \"field2\": \"value2\"}, {\"field3\": \"value3\"}]
250
+
251
+ ">
252
+ ${dataComponentsXml}
253
+ </available_data_components>`;
254
+ }
255
+ generateDataComponentXml(templates, dataComponent) {
256
+ const dataComponentTemplate = templates.get('data-component');
257
+ if (!dataComponentTemplate) {
258
+ throw new Error('Data component template not loaded');
259
+ }
260
+ let dataComponentXml = dataComponentTemplate;
261
+ // Replace data component variables
262
+ dataComponentXml = dataComponentXml.replace('{{COMPONENT_NAME}}', dataComponent.name);
263
+ dataComponentXml = dataComponentXml.replace('{{COMPONENT_DESCRIPTION}}', dataComponent.description);
264
+ dataComponentXml = dataComponentXml.replace('{{COMPONENT_PROPS_SCHEMA}}', this.generateParametersXml(dataComponent.props));
265
+ return dataComponentXml;
266
+ }
267
+ generateParametersXml(inputSchema) {
268
+ if (!inputSchema) {
269
+ return '<type>object</type>\n <properties>\n </properties>\n <required>[]</required>';
270
+ }
271
+ const schemaType = inputSchema.type || 'object';
272
+ const properties = inputSchema.properties || {};
273
+ const required = inputSchema.required || [];
274
+ // Convert JSON schema properties to XML representation
275
+ const propertiesXml = Object.entries(properties)
276
+ .map(([key, value]) => {
277
+ const isRequired = required.includes(key);
278
+ const propType = value?.type || 'string';
279
+ const propDescription = value?.description || 'No description';
280
+ return ` ${key}: {\n "type": "${propType}",\n "description": "${propDescription}",\n "required": ${isRequired}\n }`;
281
+ })
282
+ .join('\n');
283
+ return `<type>${schemaType}</type>\n <properties>\n${propertiesXml}\n </properties>\n <required>${JSON.stringify(required)}</required>`;
284
+ }
285
+ }
package/dist/app.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { OpenApiHonoWithExecutionContext } from '@inkeep/agents-core';
2
+ declare const app: OpenApiHonoWithExecutionContext;
3
+ export default app;
4
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,+BAA+B,EAAE,MAAM,qBAAqB,CAAC;AAgBtE,QAAA,MAAM,GAAG,iCAAwC,CAAC;AAuNlD,eAAe,GAAG,CAAC"}
package/dist/app.js ADDED
@@ -0,0 +1,194 @@
1
+ import { createRoute } from '@hono/zod-openapi';
2
+ import { OpenApiHonoWithExecutionContext } from '@inkeep/agents-core';
3
+ import { context as otelContext, propagation } from '@opentelemetry/api';
4
+ import { cors } from 'hono/cors';
5
+ import { HTTPException } from 'hono/http-exception';
6
+ import { requestId } from 'hono/request-id';
7
+ import { pinoLogger } from 'hono-pino';
8
+ import { handleApiError } from '@inkeep/agents-core';
9
+ import { getLogger } from './logger.js';
10
+ import { apiKeyAuth } from './middleware/api-key-auth.js';
11
+ import { setupOpenAPIRoutes } from './openapi.js';
12
+ import agentRoutes from './routes/agents.js';
13
+ import chatRoutes from './routes/chat.js';
14
+ import chatDataRoutes from './routes/chatDataStream.js';
15
+ import mcpRoutes from './routes/mcp.js';
16
+ const app = new OpenApiHonoWithExecutionContext();
17
+ // Request ID middleware
18
+ app.use('*', requestId());
19
+ // OpenTelemetry baggage middleware
20
+ app.use('*', async (c, next) => {
21
+ const reqId = c.get('requestId');
22
+ let bag = propagation.getBaggage(otelContext.active());
23
+ if (!bag) {
24
+ bag = propagation.createBaggage();
25
+ }
26
+ bag = bag.setEntry('request.id', { value: String(reqId ?? 'unknown') });
27
+ const ctxWithBag = propagation.setBaggage(otelContext.active(), bag);
28
+ return otelContext.with(ctxWithBag, () => next());
29
+ });
30
+ // Baggage middleware for execution API - extracts context from API key authentication
31
+ app.use('*', async (c, next) => {
32
+ // Get the API key context if available (set by auth middleware)
33
+ const executionContext = c.get('executionContext');
34
+ if (!executionContext) {
35
+ // No API key context, skip baggage setup
36
+ return next();
37
+ }
38
+ const { tenantId, projectId, graphId } = executionContext;
39
+ // Extract conversation ID from JSON body if present
40
+ let conversationId;
41
+ if (c.req.header('content-type')?.includes('application/json')) {
42
+ try {
43
+ const body = await c.req.json();
44
+ conversationId = body?.conversationId;
45
+ }
46
+ catch (_) {
47
+ // Silently ignore parse errors for non-JSON bodies
48
+ }
49
+ }
50
+ const entries = Object.fromEntries(Object.entries({
51
+ 'graph.id': graphId,
52
+ 'tenant.id': tenantId,
53
+ 'project.id': projectId,
54
+ 'conversation.id': conversationId,
55
+ }).filter((entry) => {
56
+ const [, v] = entry;
57
+ return typeof v === 'string' && v.length > 0;
58
+ }));
59
+ if (!Object.keys(entries).length) {
60
+ return next();
61
+ }
62
+ const bag = Object.entries(entries).reduce((b, [key, value]) => b.setEntry(key, { value: value || '' }), propagation.getBaggage(otelContext.active()) ?? propagation.createBaggage());
63
+ const ctxWithBag = propagation.setBaggage(otelContext.active(), bag);
64
+ return otelContext.with(ctxWithBag, () => next());
65
+ });
66
+ // Logging middleware
67
+ app.use(pinoLogger({
68
+ pino: getLogger(),
69
+ http: {
70
+ onResLevel(c) {
71
+ if (c.res.status >= 500) {
72
+ return 'error';
73
+ }
74
+ return 'info';
75
+ },
76
+ },
77
+ }));
78
+ // Error handling
79
+ app.onError(async (err, c) => {
80
+ const isExpectedError = err instanceof HTTPException;
81
+ const status = isExpectedError ? err.status : 500;
82
+ const requestId = c.get('requestId') || 'unknown';
83
+ // Zod validation error detection
84
+ let zodIssues;
85
+ if (err && typeof err === 'object') {
86
+ if (err.cause && Array.isArray(err.cause.issues)) {
87
+ zodIssues = err.cause.issues;
88
+ }
89
+ else if (Array.isArray(err.issues)) {
90
+ zodIssues = err.issues;
91
+ }
92
+ }
93
+ if (status === 400 && Array.isArray(zodIssues)) {
94
+ c.status(400);
95
+ c.header('Content-Type', 'application/problem+json');
96
+ c.header('X-Content-Type-Options', 'nosniff');
97
+ return c.json({
98
+ type: 'https://docs.inkeep.com/agents-api/errors#bad_request',
99
+ title: 'Validation Failed',
100
+ status: 400,
101
+ detail: 'Request validation failed',
102
+ errors: zodIssues.map((issue) => ({
103
+ detail: issue.message,
104
+ pointer: issue.path ? `/${issue.path.join('/')}` : undefined,
105
+ name: issue.path ? issue.path.join('.') : undefined,
106
+ reason: issue.message,
107
+ })),
108
+ });
109
+ }
110
+ if (status >= 500) {
111
+ if (!isExpectedError) {
112
+ const errorMessage = err instanceof Error ? err.message : String(err);
113
+ const errorStack = err instanceof Error ? err.stack : undefined;
114
+ getLogger().error({
115
+ error: err,
116
+ message: errorMessage,
117
+ stack: errorStack,
118
+ path: c.req.path,
119
+ requestId,
120
+ }, 'Unexpected server error occurred');
121
+ }
122
+ else {
123
+ getLogger().error({
124
+ error: err,
125
+ path: c.req.path,
126
+ requestId,
127
+ status,
128
+ }, 'Server error occurred');
129
+ }
130
+ }
131
+ if (isExpectedError) {
132
+ try {
133
+ const response = err.getResponse();
134
+ return response;
135
+ }
136
+ catch (responseError) {
137
+ getLogger().error({ error: responseError }, 'Error while handling HTTPException response');
138
+ }
139
+ }
140
+ const { status: respStatus, title, detail, instance } = await handleApiError(err, requestId);
141
+ c.status(respStatus);
142
+ c.header('Content-Type', 'application/problem+json');
143
+ c.header('X-Content-Type-Options', 'nosniff');
144
+ return c.json({
145
+ type: 'https://docs.inkeep.com/agents-api/errors#internal_server_error',
146
+ title,
147
+ status: respStatus,
148
+ detail,
149
+ ...(instance && { instance }),
150
+ });
151
+ });
152
+ // CORS middleware
153
+ app.use('*', cors({
154
+ origin: (origin) => {
155
+ if (!origin)
156
+ return origin;
157
+ return origin.startsWith('http://localhost:') || origin.startsWith('https://localhost:')
158
+ ? origin
159
+ : null;
160
+ },
161
+ allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
162
+ allowHeaders: ['*'],
163
+ exposeHeaders: ['Content-Length'],
164
+ maxAge: 86400,
165
+ credentials: true,
166
+ }));
167
+ // Apply API key authentication to all routes except health and docs
168
+ app.use('/tenants/*', apiKeyAuth());
169
+ app.use('/agents/*', apiKeyAuth());
170
+ app.use('/v1/*', apiKeyAuth());
171
+ app.use('/api/*', apiKeyAuth());
172
+ // Health check endpoint (no auth required)
173
+ app.openapi(createRoute({
174
+ method: 'get',
175
+ path: '/health',
176
+ tags: ['health'],
177
+ summary: 'Health check',
178
+ description: 'Check if the execution service is healthy',
179
+ responses: {
180
+ 204: {
181
+ description: 'Service is healthy',
182
+ },
183
+ },
184
+ }), (c) => {
185
+ return c.body(null, 204);
186
+ });
187
+ // Mount execution routes - API key provides tenant, project, and graph context
188
+ app.route('/v1/chat', chatRoutes);
189
+ app.route('/api', chatDataRoutes);
190
+ app.route('/v1/mcp', mcpRoutes);
191
+ app.route('/agents', agentRoutes);
192
+ // Setup OpenAPI documentation endpoints (/openapi.json and /docs)
193
+ setupOpenAPIRoutes(app);
194
+ export default app;
@@ -0,0 +1,4 @@
1
+ import type { RegisteredAgent } from '../a2a/types.js';
2
+ import type { ExecutionContext } from '@inkeep/agents-core';
3
+ export declare function getRegisteredGraph(executionContext: ExecutionContext): Promise<RegisteredAgent | null>;
4
+ //# sourceMappingURL=agentGraph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentGraph.d.ts","sourceRoot":"","sources":["../../src/data/agentGraph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,KAAK,EAAa,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AA6EvE,wBAAsB,kBAAkB,CACtC,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAUjC"}
@@ -0,0 +1,73 @@
1
+ import { createTaskHandler, createTaskHandlerConfig } from '../agents/generateTaskHandler.js';
2
+ import { getAgentById, getAgentGraph } from '@inkeep/agents-core';
3
+ import dbClient from './db/dbClient.js';
4
+ // Hydrate graph function
5
+ async function hydrateGraph({ dbGraph, baseUrl, apiKey, }) {
6
+ try {
7
+ // Get the default agent for this graph to create the task handler
8
+ const defaultAgent = await getAgentById(dbClient)({
9
+ scopes: {
10
+ tenantId: dbGraph.tenantId,
11
+ projectId: dbGraph.projectId,
12
+ },
13
+ agentId: dbGraph.defaultAgentId,
14
+ });
15
+ if (!defaultAgent) {
16
+ throw new Error(`Default agent ${dbGraph.defaultAgentId} not found for graph ${dbGraph.id}`);
17
+ }
18
+ // Create task handler for the default agent
19
+ const taskHandlerConfig = await createTaskHandlerConfig({
20
+ tenantId: dbGraph.tenantId,
21
+ projectId: dbGraph.projectId,
22
+ graphId: dbGraph.id,
23
+ agentId: dbGraph.defaultAgentId,
24
+ baseUrl: baseUrl,
25
+ apiKey: apiKey,
26
+ });
27
+ const taskHandler = createTaskHandler(taskHandlerConfig);
28
+ // Create AgentCard for the graph (representing it as a single agent)
29
+ const agentCard = {
30
+ name: dbGraph.name,
31
+ description: dbGraph.description || `Agent graph: ${dbGraph.name}`,
32
+ url: baseUrl ? `${baseUrl}/a2a` : '',
33
+ version: '1.0.0',
34
+ capabilities: {
35
+ streaming: true, // Enable streaming for A2A compliance
36
+ pushNotifications: false,
37
+ stateTransitionHistory: false,
38
+ },
39
+ defaultInputModes: ['text', 'text/plain'],
40
+ defaultOutputModes: ['text', 'text/plain'],
41
+ skills: [], // TODO: Could aggregate skills from all agents in the graph
42
+ // Add provider info if available
43
+ ...(baseUrl && {
44
+ provider: {
45
+ organization: 'Inkeep',
46
+ url: baseUrl,
47
+ },
48
+ }),
49
+ };
50
+ return {
51
+ agentId: dbGraph.id, // Use graph ID as agent ID for A2A purposes
52
+ tenantId: dbGraph.tenantId,
53
+ projectId: dbGraph.projectId,
54
+ graphId: dbGraph.id,
55
+ agentCard,
56
+ taskHandler,
57
+ };
58
+ }
59
+ catch (error) {
60
+ console.error(`❌ Failed to hydrate graph ${dbGraph.id}:`, error);
61
+ throw error;
62
+ }
63
+ }
64
+ // A2A functions that hydrate graphs on-demand
65
+ export async function getRegisteredGraph(executionContext) {
66
+ const { tenantId, projectId, graphId, baseUrl, apiKey } = executionContext;
67
+ const dbGraph = await getAgentGraph(dbClient)({ scopes: { tenantId, projectId }, graphId });
68
+ if (!dbGraph) {
69
+ return null;
70
+ }
71
+ const agentFrameworkBaseUrl = `${baseUrl}/agents`;
72
+ return hydrateGraph({ dbGraph, baseUrl: agentFrameworkBaseUrl, apiKey });
73
+ }
@@ -0,0 +1,4 @@
1
+ import type { RegisteredAgent } from '../a2a/types.js';
2
+ import { ExecutionContext } from '@inkeep/agents-core';
3
+ export declare function getRegisteredAgent(executionContext: ExecutionContext): Promise<RegisteredAgent | null>;
4
+ //# sourceMappingURL=agents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/data/agents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGlE,OAAO,EAEL,gBAAgB,EAIjB,MAAM,qBAAqB,CAAC;AAuE7B,wBAAsB,kBAAkB,CACtC,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAiBjC"}