@inkeep/agents-run-api 0.0.0-dev-20260113172432 → 0.0.0-dev-20260115183047

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 (85) hide show
  1. package/README.md +2 -1
  2. package/dist/a2a/client.d.ts +3 -1
  3. package/dist/a2a/client.js +23 -9
  4. package/dist/a2a/handlers.js +11 -5
  5. package/dist/a2a/transfer.d.ts +6 -1
  6. package/dist/a2a/transfer.js +10 -6
  7. package/dist/agents/Agent.d.ts +8 -4
  8. package/dist/agents/Agent.js +226 -92
  9. package/dist/agents/ToolSessionManager.js +2 -2
  10. package/dist/agents/generateTaskHandler.d.ts +4 -9
  11. package/dist/agents/generateTaskHandler.js +107 -246
  12. package/dist/agents/relationTools.d.ts +19 -8
  13. package/dist/agents/relationTools.js +105 -14
  14. package/dist/agents/types.d.ts +4 -2
  15. package/dist/agents/versions/v1/Phase1Config.d.ts +4 -3
  16. package/dist/agents/versions/v1/Phase1Config.js +33 -20
  17. package/dist/constants/execution-limits/index.js +1 -1
  18. package/dist/context/ContextFetcher.d.ts +68 -0
  19. package/dist/context/ContextFetcher.js +276 -0
  20. package/dist/context/ContextResolver.d.ts +56 -0
  21. package/dist/context/ContextResolver.js +273 -0
  22. package/dist/context/context.d.ts +19 -0
  23. package/dist/context/context.js +108 -0
  24. package/dist/context/contextCache.d.ts +56 -0
  25. package/dist/context/contextCache.js +175 -0
  26. package/dist/context/index.d.ts +6 -0
  27. package/dist/context/index.js +7 -0
  28. package/dist/context/validation.d.ts +39 -0
  29. package/dist/context/validation.js +255 -0
  30. package/dist/create-app.d.ts +2 -2
  31. package/dist/create-app.js +7 -2
  32. package/dist/data/agent.d.ts +2 -2
  33. package/dist/data/agent.js +17 -22
  34. package/dist/data/agents.d.ts +2 -2
  35. package/dist/data/agents.js +34 -42
  36. package/dist/data/conversations.d.ts +2 -1
  37. package/dist/data/conversations.js +7 -8
  38. package/dist/data/db/dbClient.d.ts +2 -2
  39. package/dist/data/db/dbClient.js +2 -10
  40. package/dist/env.d.ts +6 -2
  41. package/dist/env.js +3 -1
  42. package/dist/handlers/executionHandler.d.ts +3 -2
  43. package/dist/handlers/executionHandler.js +46 -22
  44. package/dist/index.d.ts +3 -3
  45. package/dist/middleware/api-key-auth.d.ts +4 -10
  46. package/dist/middleware/api-key-auth.js +164 -163
  47. package/dist/middleware/index.d.ts +3 -2
  48. package/dist/middleware/index.js +3 -2
  49. package/dist/middleware/projectConfig.d.ts +19 -0
  50. package/dist/middleware/projectConfig.js +80 -0
  51. package/dist/routes/agents.d.ts +2 -1
  52. package/dist/routes/agents.js +7 -13
  53. package/dist/routes/chat.d.ts +2 -1
  54. package/dist/routes/chat.js +29 -52
  55. package/dist/routes/chatDataStream.d.ts +2 -1
  56. package/dist/routes/chatDataStream.js +28 -30
  57. package/dist/routes/mcp.d.ts +2 -1
  58. package/dist/routes/mcp.js +25 -37
  59. package/dist/services/AgentSession.d.ts +5 -7
  60. package/dist/services/AgentSession.js +25 -34
  61. package/dist/services/ArtifactParser.d.ts +2 -2
  62. package/dist/services/ArtifactParser.js +2 -2
  63. package/dist/services/ArtifactService.d.ts +2 -3
  64. package/dist/services/ArtifactService.js +23 -20
  65. package/dist/services/BaseCompressor.js +2 -2
  66. package/dist/services/IncrementalStreamParser.d.ts +2 -2
  67. package/dist/services/IncrementalStreamParser.js +2 -2
  68. package/dist/services/ResponseFormatter.d.ts +2 -2
  69. package/dist/services/ResponseFormatter.js +2 -2
  70. package/dist/services/evaluationHttpClient.d.ts +21 -0
  71. package/dist/services/evaluationHttpClient.js +48 -0
  72. package/dist/services/evaluationRunConfigMatcher.d.ts +6 -0
  73. package/dist/services/evaluationRunConfigMatcher.js +7 -0
  74. package/dist/tools/NativeSandboxExecutor.js +1 -1
  75. package/dist/tools/distill-conversation-history-tool.js +2 -2
  76. package/dist/tools/distill-conversation-tool.js +2 -2
  77. package/dist/types/execution-context.d.ts +8 -14
  78. package/dist/types/execution-context.js +3 -2
  79. package/dist/utils/model-resolver.d.ts +2 -2
  80. package/dist/utils/model-resolver.js +3 -13
  81. package/dist/utils/project.d.ts +207 -0
  82. package/dist/utils/project.js +315 -0
  83. package/dist/utils/token-estimator.d.ts +6 -52
  84. package/dist/utils/token-estimator.js +2 -38
  85. package/package.json +2 -2
@@ -1,17 +1,22 @@
1
- import { getLogger } from "../logger.js";
1
+ import { env } from "../env.js";
2
+ import { getLogger as getLogger$1 } from "../logger.js";
2
3
  import dbClient_default from "../data/db/dbClient.js";
4
+ import { getUserIdFromContext } from "../types/execution-context.js";
3
5
  import { DELEGATION_TOOL_BACKOFF_EXPONENT, DELEGATION_TOOL_BACKOFF_INITIAL_INTERVAL_MS, DELEGATION_TOOL_BACKOFF_MAX_ELAPSED_TIME_MS, DELEGATION_TOOL_BACKOFF_MAX_INTERVAL_MS } from "../constants/execution-limits/index.js";
4
6
  import { toolSessionManager } from "./ToolSessionManager.js";
5
7
  import { saveA2AMessageResponse } from "../data/conversations.js";
6
8
  import { agentSessionManager } from "../services/AgentSession.js";
9
+ import { getExternalAgentRelationsForTargetSubAgent, getToolsForSubAgent, getTransferRelationsForTargetSubAgent } from "../utils/project.js";
10
+ import { ContextResolver } from "../context/ContextResolver.js";
11
+ import "../context/index.js";
7
12
  import { A2AClient } from "../a2a/client.js";
8
13
  import { z } from "@hono/zod-openapi";
9
- import { ContextResolver, CredentialStuffer, SPAN_KEYS, TemplateEngine, createMessage, generateId, generateServiceToken, getCredentialReference, headers } from "@inkeep/agents-core";
14
+ import { CredentialStuffer, InternalServices, ManagementApiClient, SPAN_KEYS, TemplateEngine, createMessage, generateId, generateServiceToken, headers } from "@inkeep/agents-core";
10
15
  import { trace } from "@opentelemetry/api";
11
16
  import { tool } from "ai";
12
17
 
13
18
  //#region src/agents/relationTools.ts
14
- const logger = getLogger("relationships Tools");
19
+ const logger = getLogger$1("relationships Tools");
15
20
  const A2A_RETRY_STATUS_CODES = [
16
21
  "429",
17
22
  "500",
@@ -124,7 +129,8 @@ const createTransferToAgentTool = ({ transferConfig, callingAgentId, subAgent, s
124
129
  }
125
130
  });
126
131
  };
127
- function createDelegateToAgentTool({ delegateConfig, callingAgentId, tenantId, projectId, agentId, contextId, metadata, sessionId, subAgent, credentialStoreRegistry }) {
132
+ function createDelegateToAgentTool({ delegateConfig, callingAgentId, executionContext, contextId, metadata, sessionId, subAgent, credentialStoreRegistry }) {
133
+ const { tenantId, projectId, agentId, project } = executionContext;
128
134
  return tool({
129
135
  description: generateDelegateToolDescription(delegateConfig),
130
136
  inputSchema: z.object({ message: z.string() }),
@@ -148,7 +154,7 @@ function createDelegateToAgentTool({ delegateConfig, callingAgentId, tenantId, p
148
154
  let resolvedHeaders = {};
149
155
  if (isExternal) {
150
156
  if ((delegateConfig.config.credentialReferenceId || delegateConfig.config.headers) && credentialStoreRegistry) {
151
- const credentialStuffer = new CredentialStuffer(credentialStoreRegistry, new ContextResolver(tenantId, projectId, dbClient_default, credentialStoreRegistry));
157
+ const credentialStuffer = new CredentialStuffer(credentialStoreRegistry, new ContextResolver(executionContext, credentialStoreRegistry));
152
158
  const credentialContext = {
153
159
  tenantId,
154
160
  projectId,
@@ -158,13 +164,8 @@ function createDelegateToAgentTool({ delegateConfig, callingAgentId, tenantId, p
158
164
  };
159
165
  let storeReference;
160
166
  if (delegateConfig.config.credentialReferenceId) {
161
- const credentialReference = await getCredentialReference(dbClient_default)({
162
- scopes: {
163
- tenantId,
164
- projectId
165
- },
166
- id: delegateConfig.config.credentialReferenceId
167
- });
167
+ const id = delegateConfig.config.credentialReferenceId;
168
+ const credentialReference = project.credentialReferences?.[id];
168
169
  if (credentialReference) storeReference = {
169
170
  credentialStoreId: credentialReference.credentialStoreId,
170
171
  retrievalParams: credentialReference.retrievalParams || {}
@@ -177,7 +178,7 @@ function createDelegateToAgentTool({ delegateConfig, callingAgentId, tenantId, p
177
178
  });
178
179
  }
179
180
  } else if (isTeam) {
180
- const context$2 = await new ContextResolver(tenantId, projectId, dbClient_default, credentialStoreRegistry).resolveHeaders(metadata.conversationId, contextId);
181
+ const context$2 = await new ContextResolver(executionContext, credentialStoreRegistry).resolveHeaders(metadata.conversationId, contextId);
181
182
  for (const [key, value] of Object.entries(headers)) resolvedHeaders[key] = TemplateEngine.render(value, context$2, { strict: true });
182
183
  resolvedHeaders.Authorization = `Bearer ${await generateServiceToken({
183
184
  tenantId,
@@ -235,6 +236,7 @@ function createDelegateToAgentTool({ delegateConfig, callingAgentId, tenantId, p
235
236
  fromSubAgentId: callingAgentId,
236
237
  ...isInternal ? { toSubAgentId: delegateConfig.config.id } : { toExternalAgentId: delegateConfig.config.id }
237
238
  });
239
+ logger.info({ messageToSend }, "Created message in database");
238
240
  const response = await a2aClient.sendMessage({ message: messageToSend });
239
241
  if (response.error) throw new Error(response.error.message);
240
242
  await saveA2AMessageResponse(response, {
@@ -269,6 +271,95 @@ function createDelegateToAgentTool({ delegateConfig, callingAgentId, tenantId, p
269
271
  }
270
272
  });
271
273
  }
274
+ /**
275
+ * Build a transfer relation config for an internal relation.
276
+ * Fetches tools, transfer relations, and external agent relations for the target sub-agent.
277
+ */
278
+ async function buildTransferRelationConfig(params) {
279
+ const { relation, executionContext, baseUrl, apiKey } = params;
280
+ const { tenantId, projectId, project, agentId } = executionContext;
281
+ const agent = executionContext.project.agents[agentId];
282
+ const targetSubAgent = agent.subAgents?.[relation.id];
283
+ if (!targetSubAgent) throw new Error(`Target sub-agent not found: ${relation.id}`);
284
+ const targetToolsForSubAgent = getToolsForSubAgent({
285
+ agent,
286
+ project,
287
+ subAgent: targetSubAgent
288
+ });
289
+ const manageApiClient = new ManagementApiClient({
290
+ apiUrl: env.INKEEP_AGENTS_MANAGE_API_URL,
291
+ tenantId,
292
+ projectId,
293
+ auth: {
294
+ mode: "internalService",
295
+ internalServiceName: InternalServices.INKEEP_AGENTS_RUN_API
296
+ },
297
+ ref: executionContext.resolvedRef.name,
298
+ userId: getUserIdFromContext(executionContext)
299
+ });
300
+ const targetAgentTools = await Promise.all(targetToolsForSubAgent.map(async (item) => {
301
+ const mcpTool = await manageApiClient.getMcpTool(item.tool.id);
302
+ if (item.relationshipId) mcpTool.relationshipId = item.relationshipId;
303
+ if (item.selectedTools && item.selectedTools.length > 0) {
304
+ const selectedToolsSet = new Set(item.selectedTools);
305
+ mcpTool.availableTools = mcpTool.availableTools?.filter((tool$1) => selectedToolsSet.has(tool$1.name)) || [];
306
+ }
307
+ return mcpTool;
308
+ }));
309
+ const targetTransferRelations = getTransferRelationsForTargetSubAgent({
310
+ agent,
311
+ subAgentId: relation.id
312
+ });
313
+ const targetExternalAgentRelations = getExternalAgentRelationsForTargetSubAgent({
314
+ agent,
315
+ project,
316
+ subAgentId: relation.id
317
+ });
318
+ const targetTransferRelationsConfig = targetTransferRelations.map((rel) => ({
319
+ baseUrl,
320
+ apiKey,
321
+ id: rel.id,
322
+ tenantId,
323
+ projectId,
324
+ agentId,
325
+ name: rel.name,
326
+ description: rel.description || void 0,
327
+ prompt: "",
328
+ delegateRelations: [],
329
+ subAgentRelations: [],
330
+ transferRelations: [],
331
+ project
332
+ }));
333
+ const targetDelegateRelationsConfig = targetExternalAgentRelations.map((rel) => ({
334
+ type: "external",
335
+ config: {
336
+ relationId: rel.relationId || `external-${rel.externalAgent.id}`,
337
+ id: rel.externalAgent.id,
338
+ name: rel.externalAgent.name,
339
+ description: rel.externalAgent.description || "",
340
+ ref: executionContext.resolvedRef,
341
+ baseUrl: rel.externalAgent.baseUrl,
342
+ headers: rel.headers || void 0,
343
+ credentialReferenceId: rel.externalAgent.credentialReferenceId,
344
+ relationType: "delegate"
345
+ }
346
+ }));
347
+ return {
348
+ baseUrl,
349
+ apiKey,
350
+ id: relation.id,
351
+ tenantId,
352
+ projectId,
353
+ agentId,
354
+ name: relation.name,
355
+ description: relation.description || void 0,
356
+ prompt: "",
357
+ delegateRelations: targetDelegateRelationsConfig,
358
+ subAgentRelations: [],
359
+ transferRelations: targetTransferRelationsConfig,
360
+ tools: targetAgentTools
361
+ };
362
+ }
272
363
 
273
364
  //#endregion
274
- export { createDelegateToAgentTool, createTransferToAgentTool };
365
+ export { buildTransferRelationConfig, createDelegateToAgentTool, createTransferToAgentTool };
@@ -1,10 +1,12 @@
1
1
  import { AssembleResult } from "../utils/token-estimator.js";
2
- import { Artifact, ArtifactComponentApiInsert, DataComponentApiInsert } from "@inkeep/agents-core";
2
+ import { Artifact, ArtifactComponentApiInsert, BreakdownComponentDef, DataComponentApiInsert } from "@inkeep/agents-core";
3
3
 
4
4
  //#region src/agents/types.d.ts
5
5
  interface VersionConfig<TConfig> {
6
6
  loadTemplates(): Map<string, string>;
7
7
  assemble(templates: Map<string, string>, config: TConfig): AssembleResult;
8
+ /** Returns the breakdown schema defining which components this version tracks */
9
+ getBreakdownSchema(): BreakdownComponentDef[];
8
10
  }
9
11
  interface SystemPromptV1 {
10
12
  corePrompt: string;
@@ -25,4 +27,4 @@ interface ToolData {
25
27
  usageGuidelines?: string;
26
28
  }
27
29
  //#endregion
28
- export { SystemPromptV1, ToolData, VersionConfig };
30
+ export { type BreakdownComponentDef, SystemPromptV1, ToolData, VersionConfig };
@@ -1,10 +1,11 @@
1
- import { AssembleResult } from "../../../utils/token-estimator.js";
1
+ import { AssembleResult, BreakdownComponentDef } from "../../../utils/token-estimator.js";
2
2
  import { SystemPromptV1, ToolData, VersionConfig } from "../../types.js";
3
- import { McpTool } from "@inkeep/agents-core";
3
+ import { McpTool, V1_BREAKDOWN_SCHEMA } from "@inkeep/agents-core";
4
4
 
5
5
  //#region src/agents/versions/v1/Phase1Config.d.ts
6
6
  declare class Phase1Config implements VersionConfig<SystemPromptV1> {
7
7
  loadTemplates(): Map<string, string>;
8
+ getBreakdownSchema(): BreakdownComponentDef[];
8
9
  static convertMcpToolsToToolData(mcpTools: McpTool[] | undefined): ToolData[];
9
10
  private isToolDataArray;
10
11
  private normalizeSchema;
@@ -24,4 +25,4 @@ declare class Phase1Config implements VersionConfig<SystemPromptV1> {
24
25
  private generateParametersXml;
25
26
  }
26
27
  //#endregion
27
- export { Phase1Config };
28
+ export { Phase1Config, V1_BREAKDOWN_SCHEMA };
@@ -1,14 +1,15 @@
1
- import { getLogger } from "../../../logger.js";
1
+ import { getLogger as getLogger$1 } from "../../../logger.js";
2
2
  import { calculateBreakdownTotal, createEmptyBreakdown, estimateTokens } from "../../../utils/token-estimator.js";
3
3
  import system_prompt_default from "../../../_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/system-prompt.js";
4
4
  import thinking_preparation_default from "../../../_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/thinking-preparation.js";
5
5
  import tool_default from "../../../_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/tool.js";
6
6
  import artifact_default from "../../../_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/shared/artifact.js";
7
7
  import artifact_retrieval_guidance_default from "../../../_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/shared/artifact-retrieval-guidance.js";
8
+ import { V1_BREAKDOWN_SCHEMA } from "@inkeep/agents-core";
8
9
  import { convertZodToJsonSchema, isZodSchema } from "@inkeep/agents-core/utils/schema-conversion";
9
10
 
10
11
  //#region src/agents/versions/v1/Phase1Config.ts
11
- getLogger("Phase1Config");
12
+ getLogger$1("Phase1Config");
12
13
  var Phase1Config = class Phase1Config {
13
14
  loadTemplates() {
14
15
  const templates = /* @__PURE__ */ new Map();
@@ -19,15 +20,23 @@ var Phase1Config = class Phase1Config {
19
20
  templates.set("thinking-preparation", thinking_preparation_default);
20
21
  return templates;
21
22
  }
23
+ getBreakdownSchema() {
24
+ return V1_BREAKDOWN_SCHEMA;
25
+ }
22
26
  static convertMcpToolsToToolData(mcpTools) {
23
27
  if (!mcpTools || mcpTools.length === 0) return [];
24
28
  const toolData = [];
25
- for (const mcpTool of mcpTools) if (mcpTool.availableTools) for (const toolDef of mcpTool.availableTools) toolData.push({
26
- name: toolDef.name,
27
- description: toolDef.description || "No description available",
28
- inputSchema: toolDef.inputSchema || {},
29
- usageGuidelines: `Use this tool from ${mcpTool.name} server when appropriate.`
30
- });
29
+ for (const mcpTool of mcpTools) if (mcpTool.availableTools) for (const toolDef of mcpTool.availableTools) {
30
+ let usageGuidelines = "";
31
+ if (mcpTool.config.mcp.prompt) usageGuidelines = `${mcpTool.config.mcp.prompt}\n\n`;
32
+ usageGuidelines += `Use this tool from ${mcpTool.name} server when appropriate.`;
33
+ toolData.push({
34
+ name: toolDef.name,
35
+ description: toolDef.description || "No description available",
36
+ inputSchema: toolDef.inputSchema || {},
37
+ usageGuidelines
38
+ });
39
+ }
31
40
  return toolData;
32
41
  }
33
42
  isToolDataArray(tools) {
@@ -45,17 +54,17 @@ var Phase1Config = class Phase1Config {
45
54
  return inputSchema;
46
55
  }
47
56
  assemble(templates, config) {
48
- const breakdown = createEmptyBreakdown();
57
+ const breakdown = createEmptyBreakdown(this.getBreakdownSchema());
49
58
  const systemPromptTemplateContent = templates.get("system-prompt");
50
59
  if (!systemPromptTemplateContent) throw new Error("System prompt template not loaded");
51
- breakdown.systemPromptTemplate = estimateTokens(systemPromptTemplateContent.replace("{{CORE_INSTRUCTIONS}}", "").replace("{{AGENT_CONTEXT_SECTION}}", "").replace("{{ARTIFACTS_SECTION}}", "").replace("{{TOOLS_SECTION}}", "").replace("{{THINKING_PREPARATION_INSTRUCTIONS}}", "").replace("{{TRANSFER_INSTRUCTIONS}}", "").replace("{{DELEGATION_INSTRUCTIONS}}", ""));
60
+ breakdown.components["systemPromptTemplate"] = estimateTokens(systemPromptTemplateContent.replace("{{CORE_INSTRUCTIONS}}", "").replace("{{AGENT_CONTEXT_SECTION}}", "").replace("{{ARTIFACTS_SECTION}}", "").replace("{{TOOLS_SECTION}}", "").replace("{{THINKING_PREPARATION_INSTRUCTIONS}}", "").replace("{{TRANSFER_INSTRUCTIONS}}", "").replace("{{DELEGATION_INSTRUCTIONS}}", ""));
52
61
  let systemPrompt = systemPromptTemplateContent;
53
62
  if (config.corePrompt && config.corePrompt.trim()) {
54
- breakdown.coreInstructions = estimateTokens(config.corePrompt);
63
+ breakdown.components["coreInstructions"] = estimateTokens(config.corePrompt);
55
64
  systemPrompt = systemPrompt.replace("{{CORE_INSTRUCTIONS}}", config.corePrompt);
56
65
  } else systemPrompt = systemPrompt.replace(/<core_instructions>\s*\{\{CORE_INSTRUCTIONS\}\}\s*<\/core_instructions>/g, "");
57
66
  const agentContextSection = this.generateAgentContextSection(config.prompt);
58
- breakdown.agentPrompt = estimateTokens(agentContextSection);
67
+ breakdown.components["agentPrompt"] = estimateTokens(agentContextSection);
59
68
  systemPrompt = systemPrompt.replace("{{AGENT_CONTEXT_SECTION}}", agentContextSection);
60
69
  const toolData = (this.isToolDataArray(config.tools) ? config.tools : Phase1Config.convertMcpToolsToToolData(config.tools)).map((tool) => ({
61
70
  ...tool,
@@ -64,21 +73,25 @@ var Phase1Config = class Phase1Config {
64
73
  const hasArtifactComponents = Boolean(config.artifactComponents && config.artifactComponents.length > 0);
65
74
  const artifactsSection = this.generateArtifactsSection(templates, config.artifacts, hasArtifactComponents, config.artifactComponents, config.hasAgentArtifactComponents);
66
75
  const artifactInstructionsTokens = this.getArtifactInstructionsTokens(templates, hasArtifactComponents, config.artifactComponents, config.hasAgentArtifactComponents, (config.artifacts?.length ?? 0) > 0);
67
- breakdown.systemPromptTemplate += artifactInstructionsTokens;
68
- breakdown.artifactsSection = estimateTokens(config.artifacts?.length > 0 ? config.artifacts.map((artifact) => this.generateArtifactXml(templates, artifact)).join("\n ") : "");
69
- if (hasArtifactComponents) breakdown.artifactComponents = estimateTokens(this.getArtifactCreationInstructions(hasArtifactComponents, config.artifactComponents));
76
+ breakdown.components["systemPromptTemplate"] += artifactInstructionsTokens;
77
+ const actualArtifactsXml = config.artifacts?.length > 0 ? config.artifacts.map((artifact) => this.generateArtifactXml(templates, artifact)).join("\n ") : "";
78
+ breakdown.components["artifactsSection"] = estimateTokens(actualArtifactsXml);
79
+ if (hasArtifactComponents) {
80
+ const creationInstructions = this.getArtifactCreationInstructions(hasArtifactComponents, config.artifactComponents);
81
+ breakdown.components["artifactComponents"] = estimateTokens(creationInstructions);
82
+ }
70
83
  systemPrompt = systemPrompt.replace("{{ARTIFACTS_SECTION}}", artifactsSection);
71
84
  const toolsSection = this.generateToolsSection(templates, toolData);
72
- breakdown.toolsSection = estimateTokens(toolsSection);
85
+ breakdown.components["toolsSection"] = estimateTokens(toolsSection);
73
86
  systemPrompt = systemPrompt.replace("{{TOOLS_SECTION}}", toolsSection);
74
87
  const thinkingPreparationSection = this.generateThinkingPreparationSection(templates, config.isThinkingPreparation);
75
- breakdown.thinkingPreparation = estimateTokens(thinkingPreparationSection);
88
+ breakdown.components["thinkingPreparation"] = estimateTokens(thinkingPreparationSection);
76
89
  systemPrompt = systemPrompt.replace("{{THINKING_PREPARATION_INSTRUCTIONS}}", thinkingPreparationSection);
77
90
  const transferSection = this.generateTransferInstructions(config.hasTransferRelations);
78
- breakdown.transferInstructions = estimateTokens(transferSection);
91
+ breakdown.components["transferInstructions"] = estimateTokens(transferSection);
79
92
  systemPrompt = systemPrompt.replace("{{TRANSFER_INSTRUCTIONS}}", transferSection);
80
93
  const delegationSection = this.generateDelegationInstructions(config.hasDelegateRelations);
81
- breakdown.delegationInstructions = estimateTokens(delegationSection);
94
+ breakdown.components["delegationInstructions"] = estimateTokens(delegationSection);
82
95
  systemPrompt = systemPrompt.replace("{{DELEGATION_INSTRUCTIONS}}", delegationSection);
83
96
  calculateBreakdownTotal(breakdown);
84
97
  return {
@@ -432,4 +445,4 @@ ${creationInstructions}
432
445
  };
433
446
 
434
447
  //#endregion
435
- export { Phase1Config };
448
+ export { Phase1Config, V1_BREAKDOWN_SCHEMA };
@@ -8,7 +8,7 @@ const constantsSchema = z.object(Object.fromEntries(Object.keys(executionLimitsD
8
8
  const defaultValue = executionLimitsDefaults[key];
9
9
  const envKey = `AGENTS_${key}`;
10
10
  if (typeof defaultValue === "boolean") return [envKey, z.coerce.boolean().optional()];
11
- else return [envKey, z.coerce.number().optional()];
11
+ return [envKey, z.coerce.number().optional()];
12
12
  })));
13
13
  const parseConstants = () => {
14
14
  const envOverrides = constantsSchema.parse(process.env);
@@ -0,0 +1,68 @@
1
+ import { ContextFetchDefinition, CredentialStoreRegistry, FullExecutionContext, TemplateContext } from "@inkeep/agents-core";
2
+
3
+ //#region src/context/ContextFetcher.d.ts
4
+ declare class MissingRequiredVariableError extends Error {
5
+ constructor(variable: string);
6
+ }
7
+ interface FetchResult {
8
+ data: unknown;
9
+ source: string;
10
+ durationMs: number;
11
+ }
12
+ declare class ContextFetcher {
13
+ private executionContext;
14
+ private defaultTimeout;
15
+ private credentialStuffer?;
16
+ constructor(executionContext: FullExecutionContext, credentialStoreRegistry?: CredentialStoreRegistry, defaultTimeout?: number);
17
+ /**
18
+ * Fetch data according to a fetch definition
19
+ */
20
+ fetch(definition: ContextFetchDefinition, context: TemplateContext): Promise<{
21
+ data: unknown;
22
+ resolvedUrl: string;
23
+ }>;
24
+ private getCredential;
25
+ /**
26
+ * Resolve template variables in fetch configuration and inject credential headers
27
+ */
28
+ private resolveTemplateVariables;
29
+ /**
30
+ * Interpolate template variables in a string using TemplateEngine
31
+ */
32
+ private interpolateTemplate;
33
+ /**
34
+ * Interpolate template variables in an object recursively using TemplateEngine
35
+ */
36
+ private interpolateObjectTemplates;
37
+ /**
38
+ * Perform HTTP request
39
+ */
40
+ private performRequest;
41
+ /**
42
+ * Transform response data using JsonTransformer (JMESPath)
43
+ */
44
+ private transformResponse;
45
+ /**
46
+ * Validate response against JSON Schema
47
+ */
48
+ private validateResponseWithJsonSchema;
49
+ /**
50
+ * Test a fetch definition without caching
51
+ */
52
+ test(definition: ContextFetchDefinition, context: TemplateContext): Promise<{
53
+ success: boolean;
54
+ data?: unknown;
55
+ resolvedUrl?: string;
56
+ error?: string;
57
+ durationMs: number;
58
+ }>;
59
+ /**
60
+ * Get fetcher statistics
61
+ */
62
+ getStats(): {
63
+ tenantId: string;
64
+ defaultTimeout: number;
65
+ };
66
+ }
67
+ //#endregion
68
+ export { ContextFetcher, FetchResult, MissingRequiredVariableError };
@@ -0,0 +1,276 @@
1
+ import { validateAgainstJsonSchema } from "./validation.js";
2
+ import { CredentialStuffer, JsonTransformer, TemplateEngine, getLogger } from "@inkeep/agents-core";
3
+
4
+ //#region src/context/ContextFetcher.ts
5
+ const logger = getLogger("context-fetcher");
6
+ var MissingRequiredVariableError = class extends Error {
7
+ constructor(variable) {
8
+ super(`Missing required variable: ${variable}`);
9
+ this.name = "MissingRequiredVariableError";
10
+ }
11
+ };
12
+ /**
13
+ * GraphQL error checker - validates response for GraphQL errors and throws if found
14
+ */
15
+ const checkGraphQLErrors = (data) => {
16
+ if (data && typeof data === "object" && "errors" in data) {
17
+ const errorObj = data;
18
+ if (Array.isArray(errorObj.errors) && errorObj.errors.length > 0) {
19
+ const agentqlErrors = errorObj.errors;
20
+ const errorMessage = `GraphQL request failed with ${agentqlErrors.length} errors: ${agentqlErrors.map((e) => e.message || "Unknown error").join(", ")}`;
21
+ throw new Error(errorMessage);
22
+ }
23
+ }
24
+ };
25
+ const responseErrorCheckers = [checkGraphQLErrors];
26
+ var ContextFetcher = class {
27
+ executionContext;
28
+ defaultTimeout;
29
+ credentialStuffer;
30
+ constructor(executionContext, credentialStoreRegistry, defaultTimeout = 1e4) {
31
+ this.executionContext = executionContext;
32
+ this.defaultTimeout = defaultTimeout;
33
+ if (credentialStoreRegistry) this.credentialStuffer = new CredentialStuffer(credentialStoreRegistry);
34
+ logger.info({
35
+ tenantId: this.executionContext.tenantId,
36
+ defaultTimeout: this.defaultTimeout,
37
+ hasCredentialSupport: !!this.credentialStuffer
38
+ }, "ContextFetcher initialized");
39
+ }
40
+ /**
41
+ * Fetch data according to a fetch definition
42
+ */
43
+ async fetch(definition, context) {
44
+ const startTime = Date.now();
45
+ logger.info({
46
+ definitionId: definition.id,
47
+ url: definition.fetchConfig.url
48
+ }, "Starting context fetch");
49
+ try {
50
+ const resolvedConfig = await this.resolveTemplateVariables(definition.fetchConfig, context, definition.credentialReferenceId);
51
+ const response = await this.performRequest(resolvedConfig);
52
+ let transformedData = response.data;
53
+ if (definition.fetchConfig.transform) transformedData = await this.transformResponse(response.data, definition.fetchConfig.transform);
54
+ if (definition.responseSchema) this.validateResponseWithJsonSchema(transformedData, definition.responseSchema, definition.id);
55
+ const durationMs = Date.now() - startTime;
56
+ logger.info({
57
+ definitionId: definition.id,
58
+ source: response.source,
59
+ durationMs
60
+ }, "Context fetch completed successfully");
61
+ return {
62
+ data: transformedData,
63
+ resolvedUrl: resolvedConfig.url
64
+ };
65
+ } catch (error) {
66
+ const durationMs = Date.now() - startTime;
67
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
68
+ if (error instanceof MissingRequiredVariableError) logger.error({
69
+ definitionId: definition.id,
70
+ error: errorMessage,
71
+ durationMs
72
+ }, "Context fetch skipped due to missing required variable");
73
+ logger.error({
74
+ definitionId: definition.id,
75
+ error: errorMessage,
76
+ durationMs
77
+ }, "Context fetch failed");
78
+ throw error;
79
+ }
80
+ }
81
+ async getCredential(credentialReferenceId) {
82
+ const { project, tenantId, projectId } = this.executionContext;
83
+ try {
84
+ const credentialReference = project.credentialReferences?.[credentialReferenceId];
85
+ logger.info({ credentialReference }, "Credential reference");
86
+ if (!credentialReference || !this.credentialStuffer) throw new Error(`Credential store not found for reference ID: ${credentialReferenceId}`);
87
+ const credentialContext = {
88
+ tenantId,
89
+ projectId
90
+ };
91
+ const storeReference = {
92
+ credentialStoreId: credentialReference.credentialStoreId,
93
+ retrievalParams: credentialReference.retrievalParams || {}
94
+ };
95
+ return await this.credentialStuffer.getCredentials(credentialContext, storeReference);
96
+ } catch (error) {
97
+ logger.error({
98
+ credentialReferenceId,
99
+ error: error instanceof Error ? error.message : "Unknown error"
100
+ }, "Failed to resolve credentials for fetch request");
101
+ throw error;
102
+ }
103
+ }
104
+ /**
105
+ * Resolve template variables in fetch configuration and inject credential headers
106
+ */
107
+ async resolveTemplateVariables(fetchConfig, context, credentialReferenceId) {
108
+ const resolved = { ...fetchConfig };
109
+ const filteredRequiredToFetch = fetchConfig.requiredToFetch?.filter((variable) => variable.startsWith("{{") && variable.endsWith("}}"));
110
+ if (filteredRequiredToFetch) for (const variable of filteredRequiredToFetch) {
111
+ let resolvedVariable;
112
+ try {
113
+ resolvedVariable = this.interpolateTemplate(variable, context);
114
+ } catch {
115
+ throw new MissingRequiredVariableError(variable);
116
+ }
117
+ if (resolvedVariable === "" || resolvedVariable === variable) throw new MissingRequiredVariableError(variable);
118
+ }
119
+ resolved.url = this.interpolateTemplate(fetchConfig.url, context);
120
+ logger.info({ resolvedUrl: resolved.url }, "Resolved URL");
121
+ if (fetchConfig.headers) {
122
+ resolved.headers = {};
123
+ for (const [key, value] of Object.entries(fetchConfig.headers)) resolved.headers[key] = this.interpolateTemplate(value, context);
124
+ }
125
+ if (fetchConfig.body) resolved.body = this.interpolateObjectTemplates(fetchConfig.body, context);
126
+ if (credentialReferenceId && this.credentialStuffer) try {
127
+ const credentialHeaders = (await this.getCredential(credentialReferenceId))?.headers;
128
+ if (credentialHeaders) {
129
+ resolved.headers = {
130
+ ...resolved.headers,
131
+ ...credentialHeaders
132
+ };
133
+ logger.info({ credentialReferenceId }, "Added credential headers to fetch request");
134
+ }
135
+ } catch (error) {
136
+ logger.error({
137
+ credentialReferenceId,
138
+ error: error instanceof Error ? error.message : "Unknown error"
139
+ }, "Failed to resolve credentials for fetch request");
140
+ throw error;
141
+ }
142
+ return resolved;
143
+ }
144
+ /**
145
+ * Interpolate template variables in a string using TemplateEngine
146
+ */
147
+ interpolateTemplate(template, context) {
148
+ try {
149
+ return TemplateEngine.render(template, context, {
150
+ strict: false,
151
+ preserveUnresolved: true
152
+ });
153
+ } catch (error) {
154
+ logger.error({
155
+ template,
156
+ error: error instanceof Error ? error.message : "Unknown error"
157
+ }, "Failed to interpolate template variable");
158
+ return template;
159
+ }
160
+ }
161
+ /**
162
+ * Interpolate template variables in an object recursively using TemplateEngine
163
+ */
164
+ interpolateObjectTemplates(obj, context) {
165
+ const result = {};
166
+ for (const [key, value] of Object.entries(obj)) if (typeof value === "string") result[key] = this.interpolateTemplate(value, context);
167
+ else if (value && typeof value === "object" && !Array.isArray(value)) result[key] = this.interpolateObjectTemplates(value, context);
168
+ else result[key] = value;
169
+ return result;
170
+ }
171
+ /**
172
+ * Perform HTTP request
173
+ */
174
+ async performRequest(config) {
175
+ const startTime = Date.now();
176
+ try {
177
+ logger.debug({
178
+ url: config.url,
179
+ method: config.method
180
+ }, "Performing HTTP request");
181
+ const response = await fetch(config.url, {
182
+ method: config.method,
183
+ headers: config.headers,
184
+ body: config.body ? JSON.stringify(config.body) : void 0,
185
+ signal: AbortSignal.timeout(config.timeout || this.defaultTimeout)
186
+ });
187
+ if (!response.ok) {
188
+ const errorText = await response.text();
189
+ throw /* @__PURE__ */ new Error(`HTTP ${response.status}: ${response.statusText} - ${errorText}`);
190
+ }
191
+ const contentType = response.headers.get("content-type") || "";
192
+ let data;
193
+ if (contentType.includes("application/json")) data = await response.json();
194
+ else data = await response.text();
195
+ const durationMs = Date.now() - startTime;
196
+ for (const checker of responseErrorCheckers) checker(data);
197
+ return {
198
+ data,
199
+ source: config.url,
200
+ durationMs
201
+ };
202
+ } catch (error) {
203
+ const durationMs = Date.now() - startTime;
204
+ const requestError = error instanceof Error ? error : /* @__PURE__ */ new Error("Unknown error");
205
+ logger.warn({
206
+ url: config.url,
207
+ error: requestError.message,
208
+ durationMs
209
+ }, "HTTP request failed");
210
+ throw requestError;
211
+ }
212
+ }
213
+ /**
214
+ * Transform response data using JsonTransformer (JMESPath)
215
+ */
216
+ async transformResponse(data, transform) {
217
+ try {
218
+ return await JsonTransformer.transform(data, transform);
219
+ } catch (error) {
220
+ logger.error({
221
+ transform,
222
+ error: error instanceof Error ? error.message : "Unknown error"
223
+ }, "Failed to transform response data");
224
+ return data;
225
+ }
226
+ }
227
+ /**
228
+ * Validate response against JSON Schema
229
+ */
230
+ validateResponseWithJsonSchema(data, jsonSchema, definitionId) {
231
+ try {
232
+ if (!validateAgainstJsonSchema(jsonSchema, data)) throw new Error("Data does not match JSON Schema");
233
+ } catch (error) {
234
+ const errorMessage = error instanceof Error ? error.message : "Unknown validation error";
235
+ logger.error({
236
+ definitionId,
237
+ jsonSchema,
238
+ error: errorMessage
239
+ }, "JSON Schema response validation failed");
240
+ throw new Error(`Response validation failed: ${errorMessage}`);
241
+ }
242
+ }
243
+ /**
244
+ * Test a fetch definition without caching
245
+ */
246
+ async test(definition, context) {
247
+ const startTime = Date.now();
248
+ try {
249
+ const result = await this.fetch(definition, context);
250
+ return {
251
+ success: true,
252
+ data: result.data,
253
+ resolvedUrl: result.resolvedUrl,
254
+ durationMs: Date.now() - startTime
255
+ };
256
+ } catch (error) {
257
+ return {
258
+ success: false,
259
+ error: error instanceof Error ? error.message : "Unknown error",
260
+ durationMs: Date.now() - startTime
261
+ };
262
+ }
263
+ }
264
+ /**
265
+ * Get fetcher statistics
266
+ */
267
+ getStats() {
268
+ return {
269
+ tenantId: this.executionContext.tenantId,
270
+ defaultTimeout: this.defaultTimeout
271
+ };
272
+ }
273
+ };
274
+
275
+ //#endregion
276
+ export { ContextFetcher, MissingRequiredVariableError };