@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
@@ -0,0 +1,56 @@
1
+ import { ContextConfigApiSelect, CredentialStoreRegistry, FullExecutionContext } from "@inkeep/agents-core";
2
+
3
+ //#region src/context/ContextResolver.d.ts
4
+ interface ResolvedContext {
5
+ [templateKey: string]: unknown;
6
+ }
7
+ interface ContextResolutionOptions {
8
+ triggerEvent: 'initialization' | 'invocation';
9
+ conversationId: string;
10
+ headers?: Record<string, unknown>;
11
+ tenantId: string;
12
+ }
13
+ interface ContextResolutionResult {
14
+ resolvedContext: ResolvedContext;
15
+ headers: Record<string, unknown>;
16
+ fetchedDefinitions: string[];
17
+ cacheHits: string[];
18
+ cacheMisses: string[];
19
+ errors: Array<{
20
+ definitionId: string;
21
+ error: string;
22
+ }>;
23
+ skipped: Array<{
24
+ definitionId: string;
25
+ reason: string;
26
+ }>;
27
+ totalDurationMs: number;
28
+ }
29
+ declare class ContextResolver {
30
+ private fetcher;
31
+ private cache;
32
+ private executionContext;
33
+ constructor(executionContext: FullExecutionContext, credentialStoreRegistry?: CredentialStoreRegistry);
34
+ /**
35
+ * Resolve all contexts for a given configuration and trigger event
36
+ */
37
+ resolve(contextConfig: ContextConfigApiSelect, options: ContextResolutionOptions): Promise<ContextResolutionResult>;
38
+ /**
39
+ * Resolve a single context variable
40
+ */
41
+ private resolveSingleFetchDefinition;
42
+ /**
43
+ * Resolve the headers for a given conversation
44
+ */
45
+ resolveHeaders(conversationId: string, contextConfigId: string): Promise<Record<string, unknown>>;
46
+ /**
47
+ * Create a hash of the headers for cache invalidation
48
+ */
49
+ private createRequestHash;
50
+ /**
51
+ * Clear cache
52
+ */
53
+ clearCache(tenantId: string, projectId: string, conversationId: string): Promise<void>;
54
+ }
55
+ //#endregion
56
+ export { ContextResolutionOptions, ContextResolutionResult, ContextResolver, ResolvedContext };
@@ -0,0 +1,273 @@
1
+ import { ContextCache } from "./contextCache.js";
2
+ import { ContextFetcher, MissingRequiredVariableError } from "./ContextFetcher.js";
3
+ import { getLogger, getTracer, setSpanWithError } from "@inkeep/agents-core";
4
+ import { SpanStatusCode } from "@opentelemetry/api";
5
+ import crypto from "node:crypto";
6
+
7
+ //#region src/context/ContextResolver.ts
8
+ const logger = getLogger("context-resolver");
9
+ const tracer = getTracer("context-resolver");
10
+ var ContextResolver = class {
11
+ fetcher;
12
+ cache;
13
+ executionContext;
14
+ constructor(executionContext, credentialStoreRegistry) {
15
+ this.executionContext = executionContext;
16
+ this.fetcher = new ContextFetcher(executionContext, credentialStoreRegistry);
17
+ this.cache = new ContextCache(executionContext);
18
+ logger.info({
19
+ tenantId: this.executionContext.tenantId,
20
+ hasCredentialSupport: !!credentialStoreRegistry
21
+ }, "ContextResolver initialized");
22
+ }
23
+ /**
24
+ * Resolve all contexts for a given configuration and trigger event
25
+ */
26
+ async resolve(contextConfig, options) {
27
+ const startTime = Date.now();
28
+ logger.info({
29
+ contextConfigId: contextConfig.id,
30
+ triggerEvent: options.triggerEvent,
31
+ conversationId: options.conversationId
32
+ }, "Starting context resolution");
33
+ return tracer.startActiveSpan("context.resolve", { attributes: {
34
+ "context.config_id": contextConfig.id,
35
+ "context.trigger_event": options.triggerEvent
36
+ } }, async (parentSpan) => {
37
+ try {
38
+ const result = {
39
+ resolvedContext: {},
40
+ headers: options.headers || {},
41
+ fetchedDefinitions: [],
42
+ cacheHits: [],
43
+ cacheMisses: [],
44
+ errors: [],
45
+ skipped: [],
46
+ totalDurationMs: 0
47
+ };
48
+ result.resolvedContext.headers = result.headers;
49
+ const currentHeaders = await this.cache.get({
50
+ conversationId: options.conversationId,
51
+ contextConfigId: contextConfig.id,
52
+ contextVariableKey: "headers"
53
+ });
54
+ if (options.headers && Object.keys(options.headers).length > 0) {
55
+ await this.cache.invalidateHeaders(this.executionContext.tenantId, this.executionContext.projectId, options.conversationId, contextConfig.id);
56
+ logger.info({
57
+ conversationId: options.conversationId,
58
+ contextConfigId: contextConfig.id
59
+ }, "Invalidated headers in cache");
60
+ await this.cache.set({
61
+ contextConfigId: contextConfig.id,
62
+ contextVariableKey: "headers",
63
+ conversationId: options.conversationId,
64
+ value: options.headers,
65
+ tenantId: this.executionContext.tenantId
66
+ });
67
+ logger.info({
68
+ conversationId: options.conversationId,
69
+ contextConfigId: contextConfig.id
70
+ }, "Headers set in cache");
71
+ } else if (currentHeaders) result.headers = currentHeaders.value;
72
+ else result.headers = {};
73
+ result.resolvedContext.headers = result.headers;
74
+ const contextVariables = contextConfig.contextVariables || {};
75
+ const contextVariableEntries = Object.entries(contextVariables);
76
+ if (contextVariableEntries.length === 0) {
77
+ logger.info({ contextConfigId: contextConfig.id }, "No context variables in context config");
78
+ result.totalDurationMs = Date.now() - startTime;
79
+ parentSpan.setStatus({ code: SpanStatusCode.OK });
80
+ return result;
81
+ }
82
+ contextVariableEntries.filter(([, def]) => def.trigger === "initialization");
83
+ const invocationDefs = contextVariableEntries.filter(([, def]) => def.trigger === "invocation");
84
+ if (options.triggerEvent === "invocation" && invocationDefs.length > 0) await this.cache.invalidateInvocationDefinitions(this.executionContext.tenantId, this.executionContext.projectId, options.conversationId, contextConfig.id, invocationDefs.map(([, def]) => def.id));
85
+ const requestHash = this.createRequestHash(result.headers);
86
+ const fetchPromises = contextVariableEntries.map(([templateKey, definition]) => this.resolveSingleFetchDefinition(contextConfig, definition, templateKey, options, requestHash, result).catch((error) => {
87
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
88
+ if (error instanceof MissingRequiredVariableError) {
89
+ logger.info({
90
+ contextConfigId: contextConfig.id,
91
+ definitionId: definition.id,
92
+ templateKey,
93
+ reason: errorMessage
94
+ }, "Context fetch skipped due to missing required variable");
95
+ result.skipped.push({
96
+ definitionId: definition.id,
97
+ reason: errorMessage
98
+ });
99
+ if (definition.defaultValue !== void 0) {
100
+ result.resolvedContext[templateKey] = definition.defaultValue;
101
+ logger.info({
102
+ contextConfigId: contextConfig.id,
103
+ definitionId: definition.id,
104
+ templateKey
105
+ }, "Using default value for skipped context variable");
106
+ }
107
+ return;
108
+ }
109
+ logger.error({
110
+ contextConfigId: contextConfig.id,
111
+ definitionId: definition.id,
112
+ templateKey,
113
+ error: errorMessage
114
+ }, "Failed to resolve context variable");
115
+ result.errors.push({
116
+ definitionId: definition.id,
117
+ error: errorMessage
118
+ });
119
+ if (definition.defaultValue !== void 0) {
120
+ result.resolvedContext[templateKey] = definition.defaultValue;
121
+ logger.info({
122
+ contextConfigId: contextConfig.id,
123
+ definitionId: definition.id,
124
+ templateKey
125
+ }, "Using default value for failed context variable");
126
+ }
127
+ }));
128
+ await Promise.all(fetchPromises);
129
+ result.totalDurationMs = Date.now() - startTime;
130
+ parentSpan.addEvent("context.resolution.completed", {
131
+ resolved_keys: Object.keys(result.resolvedContext),
132
+ fetched_definitions: result.fetchedDefinitions,
133
+ skipped_definitions: result.skipped.map((s) => s.definitionId)
134
+ });
135
+ if (result.errors.length > 0) parentSpan.setStatus({
136
+ code: SpanStatusCode.ERROR,
137
+ message: `Context resolution completed with errors`
138
+ });
139
+ else parentSpan.setStatus({ code: SpanStatusCode.OK });
140
+ logger.info({
141
+ contextConfigId: contextConfig.id,
142
+ resolvedKeys: Object.keys(result.resolvedContext),
143
+ fetchedDefinitions: result.fetchedDefinitions.length,
144
+ cacheHits: result.cacheHits.length,
145
+ cacheMisses: result.cacheMisses.length,
146
+ errors: result.errors.length,
147
+ skipped: result.skipped.length,
148
+ totalDurationMs: result.totalDurationMs
149
+ }, "Context resolution completed");
150
+ return result;
151
+ } catch (error) {
152
+ const durationMs = Date.now() - startTime;
153
+ setSpanWithError(parentSpan, error instanceof Error ? error : new Error(String(error)));
154
+ logger.error({
155
+ contextConfigId: contextConfig.id,
156
+ error: error instanceof Error ? error.message : String(error),
157
+ durationMs
158
+ }, "Context resolution failed");
159
+ throw error;
160
+ } finally {
161
+ parentSpan.end();
162
+ }
163
+ });
164
+ }
165
+ /**
166
+ * Resolve a single context variable
167
+ */
168
+ async resolveSingleFetchDefinition(contextConfig, definition, templateKey, options, requestHash, result) {
169
+ const cachedEntry = await this.cache.get({
170
+ conversationId: options.conversationId,
171
+ contextConfigId: contextConfig.id,
172
+ contextVariableKey: templateKey,
173
+ requestHash
174
+ });
175
+ if (cachedEntry) {
176
+ result.resolvedContext[templateKey] = cachedEntry.value;
177
+ result.cacheHits.push(definition.id);
178
+ logger.debug({
179
+ definitionId: definition.id,
180
+ templateKey,
181
+ conversationId: options.conversationId
182
+ }, "Cache hit for context variable");
183
+ return;
184
+ }
185
+ result.cacheMisses.push(definition.id);
186
+ logger.debug({
187
+ definitionId: definition.id,
188
+ templateKey,
189
+ conversationId: options.conversationId
190
+ }, "Cache miss for context variable, fetching data");
191
+ const definitionWithConversationId = {
192
+ ...definition,
193
+ fetchConfig: {
194
+ ...definition.fetchConfig,
195
+ conversationId: options.conversationId
196
+ }
197
+ };
198
+ const fetchedData = await tracer.startActiveSpan("context-resolver.resolve_single_fetch_definition", { attributes: {
199
+ "context.definition_id": definition.id,
200
+ "context.template_key": templateKey,
201
+ "context.url_template": definition.fetchConfig.url,
202
+ "context.method": definition.fetchConfig.method,
203
+ "context.trigger": definition.trigger
204
+ } }, async (parentSpan) => {
205
+ try {
206
+ const { data, resolvedUrl } = await this.fetcher.fetch(definitionWithConversationId, result.resolvedContext);
207
+ parentSpan.setStatus({ code: SpanStatusCode.OK });
208
+ parentSpan.addEvent("context.fetch_success", {
209
+ definition_id: definition.id,
210
+ template_key: templateKey,
211
+ source: resolvedUrl
212
+ });
213
+ return data;
214
+ } catch (error) {
215
+ if (error instanceof MissingRequiredVariableError) {
216
+ parentSpan.setStatus({ code: SpanStatusCode.OK });
217
+ parentSpan.addEvent("context.fetch_skipped", {
218
+ definition_id: definition.id,
219
+ template_key: templateKey,
220
+ reason: error.message
221
+ });
222
+ } else setSpanWithError(parentSpan, error instanceof Error ? error : new Error(String(error)));
223
+ throw error;
224
+ } finally {
225
+ parentSpan.end();
226
+ }
227
+ });
228
+ result.resolvedContext[templateKey] = fetchedData;
229
+ result.fetchedDefinitions.push(definition.id);
230
+ await this.cache.set({
231
+ contextConfigId: contextConfig.id,
232
+ contextVariableKey: templateKey,
233
+ conversationId: options.conversationId,
234
+ value: fetchedData,
235
+ requestHash,
236
+ tenantId: this.executionContext.tenantId
237
+ });
238
+ logger.debug({
239
+ definitionId: definition.id,
240
+ templateKey,
241
+ conversationId: options.conversationId
242
+ }, "Context variable resolved and cached");
243
+ }
244
+ /**
245
+ * Resolve the headers for a given conversation
246
+ */
247
+ async resolveHeaders(conversationId, contextConfigId) {
248
+ const cachedEntry = await this.cache.get({
249
+ conversationId,
250
+ contextConfigId,
251
+ contextVariableKey: "headers"
252
+ });
253
+ if (cachedEntry) return cachedEntry.value;
254
+ return {};
255
+ }
256
+ /**
257
+ * Create a hash of the headers for cache invalidation
258
+ */
259
+ createRequestHash(headers$1) {
260
+ const contextString = JSON.stringify(headers$1, Object.keys(headers$1).sort());
261
+ return crypto.createHash("sha256").update(contextString).digest("hex").substring(0, 16);
262
+ }
263
+ /**
264
+ * Clear cache
265
+ */
266
+ async clearCache(tenantId, projectId, conversationId) {
267
+ await this.cache.clearConversation(tenantId, projectId, conversationId);
268
+ logger.info({ conversationId }, "Context cache cleared for conversation");
269
+ }
270
+ };
271
+
272
+ //#endregion
273
+ export { ContextResolver };
@@ -0,0 +1,19 @@
1
+ import { ResolvedContext } from "./ContextResolver.js";
2
+ import { CredentialStoreRegistry, FullExecutionContext } from "@inkeep/agents-core";
3
+
4
+ //#region src/context/context.d.ts
5
+ declare function determineContextTrigger(tenantId: string, projectId: string, conversationId: string): Promise<'initialization' | 'invocation'>;
6
+ declare function handleContextConfigChange(executionContext: FullExecutionContext, conversationId: string, newContextConfigId: string, credentialStores?: CredentialStoreRegistry): Promise<void>;
7
+ declare function handleContextResolution({
8
+ executionContext,
9
+ conversationId,
10
+ headers,
11
+ credentialStores
12
+ }: {
13
+ executionContext: FullExecutionContext;
14
+ conversationId: string;
15
+ headers: Record<string, unknown>;
16
+ credentialStores?: CredentialStoreRegistry;
17
+ }): Promise<ResolvedContext | null>;
18
+ //#endregion
19
+ export { determineContextTrigger, handleContextConfigChange, handleContextResolution };
@@ -0,0 +1,108 @@
1
+ import dbClient_default from "../data/db/dbClient.js";
2
+ import { ContextResolver } from "./ContextResolver.js";
3
+ import { getConversation, getLogger, getTracer, setSpanWithError, updateConversation } from "@inkeep/agents-core";
4
+ import { SpanStatusCode } from "@opentelemetry/api";
5
+
6
+ //#region src/context/context.ts
7
+ const logger = getLogger("context");
8
+ const tracer = getTracer("context");
9
+ async function determineContextTrigger(tenantId, projectId, conversationId) {
10
+ const conversation = await getConversation(dbClient_default)({
11
+ scopes: {
12
+ tenantId,
13
+ projectId
14
+ },
15
+ conversationId
16
+ });
17
+ if (!conversation || !conversation.lastContextResolution) return "initialization";
18
+ return "invocation";
19
+ }
20
+ async function handleContextConfigChange(executionContext, conversationId, newContextConfigId, credentialStores) {
21
+ const { tenantId, projectId, agentId } = executionContext;
22
+ const conversation = await getConversation(dbClient_default)({
23
+ scopes: {
24
+ tenantId,
25
+ projectId
26
+ },
27
+ conversationId
28
+ });
29
+ if (!conversation) return;
30
+ if (conversation.lastContextResolution) {
31
+ await new ContextResolver(executionContext, credentialStores).clearCache(tenantId, projectId, conversationId);
32
+ logger.info({
33
+ conversationId,
34
+ agentId,
35
+ contextConfigId: newContextConfigId
36
+ }, "Potential context config change for existing conversation, cache cleared");
37
+ }
38
+ }
39
+ async function handleContextResolution({ executionContext, conversationId, headers: headers$1, credentialStores }) {
40
+ return tracer.startActiveSpan("context.handle_context_resolution", { attributes: { "context.headers_keys": Object.keys(headers$1) } }, async (parentSpan) => {
41
+ const { tenantId, projectId, agentId, project } = executionContext;
42
+ const agent = project.agents[agentId];
43
+ let trigger;
44
+ try {
45
+ const contextConfig = agent.contextConfig;
46
+ if (!contextConfig) {
47
+ logger.debug({ agentId }, "No context config found for agent");
48
+ return null;
49
+ }
50
+ await handleContextConfigChange(executionContext, conversationId, contextConfig.id, credentialStores);
51
+ trigger = await determineContextTrigger(tenantId, projectId, conversationId);
52
+ const contextResult = await new ContextResolver(executionContext, credentialStores).resolve(contextConfig, {
53
+ triggerEvent: trigger,
54
+ conversationId,
55
+ headers: headers$1,
56
+ tenantId
57
+ });
58
+ logger.info({ contextResult }, "Context result");
59
+ const resolvedContext = {
60
+ ...contextResult.resolvedContext,
61
+ $env: process.env
62
+ };
63
+ await updateConversation(dbClient_default)({
64
+ scopes: {
65
+ tenantId,
66
+ projectId
67
+ },
68
+ conversationId,
69
+ data: { lastContextResolution: (/* @__PURE__ */ new Date()).toISOString() }
70
+ });
71
+ if (contextResult.errors.length > 0) parentSpan.setStatus({
72
+ code: SpanStatusCode.ERROR,
73
+ message: `Context resolution completed with errors`
74
+ });
75
+ else parentSpan.setStatus({ code: SpanStatusCode.OK });
76
+ logger.info({
77
+ conversationId,
78
+ agentId,
79
+ contextConfigId: contextConfig.id,
80
+ trigger,
81
+ resolvedKeys: Object.keys(resolvedContext),
82
+ cacheHits: contextResult.cacheHits.length,
83
+ cacheMisses: contextResult.cacheMisses.length,
84
+ fetchedDefinitions: contextResult.fetchedDefinitions.length,
85
+ errors: contextResult.errors.length
86
+ }, "Context resolution completed (contextConfigId derived from agent)");
87
+ return resolvedContext;
88
+ } catch (error) {
89
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
90
+ parentSpan.setAttributes({
91
+ "context.final_status": "failed",
92
+ "context.error_message": errorMessage
93
+ });
94
+ setSpanWithError(parentSpan, error instanceof Error ? error : new Error(String(error)));
95
+ logger.error({
96
+ error: errorMessage,
97
+ contextConfigId: agent?.contextConfig?.id,
98
+ trigger: await determineContextTrigger(tenantId, projectId, conversationId).catch(() => "unknown")
99
+ }, "Failed to resolve context, proceeding without context resolution");
100
+ return null;
101
+ } finally {
102
+ parentSpan.end();
103
+ }
104
+ });
105
+ }
106
+
107
+ //#endregion
108
+ export { determineContextTrigger, handleContextConfigChange, handleContextResolution };
@@ -0,0 +1,56 @@
1
+ import { FullExecutionContext } from "@inkeep/agents-core";
2
+
3
+ //#region src/context/contextCache.d.ts
4
+ interface CacheEntry {
5
+ contextConfigId: string;
6
+ contextVariableKey: string;
7
+ conversationId: string;
8
+ value: unknown;
9
+ requestHash?: string;
10
+ tenantId: string;
11
+ }
12
+ /**
13
+ * Context cache with request hash-based invalidation and graceful error handling.
14
+ *
15
+ * Implements conversation-scoped caching with smart cache invalidation based on
16
+ * request hash changes. All cache errors are treated as cache misses to ensure
17
+ * system reliability.
18
+ */
19
+ declare class ContextCache {
20
+ private executionContext;
21
+ constructor(executionContext: FullExecutionContext);
22
+ /**
23
+ * Get cached context data for a conversation
24
+ */
25
+ get({
26
+ conversationId,
27
+ contextConfigId,
28
+ contextVariableKey,
29
+ requestHash
30
+ }: {
31
+ conversationId: string;
32
+ contextConfigId: string;
33
+ contextVariableKey: string;
34
+ requestHash?: string;
35
+ }): Promise<CacheEntry | null>;
36
+ /**
37
+ * Set cached context data for a conversation
38
+ */
39
+ set(entry: CacheEntry): Promise<void>;
40
+ /**
41
+ * Clear cache entries for a specific conversation
42
+ */
43
+ clearConversation(tenantId: string, projectId: string, conversationId: string): Promise<void>;
44
+ /**
45
+ * Clear all cache entries for a specific context configuration
46
+ */
47
+ clearContextConfig(tenantId: string, projectId: string, contextConfigId: string): Promise<void>;
48
+ /**
49
+ * Clean up expired or orphaned cache entries
50
+ */
51
+ cleanup(): Promise<void>;
52
+ invalidateInvocationDefinitions(tenantId: string, projectId: string, conversationId: string, contextConfigId: string, definitionIds: string[]): Promise<void>;
53
+ invalidateHeaders(tenantId: string, projectId: string, conversationId: string, contextConfigId: string): Promise<void>;
54
+ }
55
+ //#endregion
56
+ export { CacheEntry, ContextCache };
@@ -0,0 +1,175 @@
1
+ import dbClient_default from "../data/db/dbClient.js";
2
+ import { cleanupTenantCache, clearContextConfigCache, clearConversationCache, generateId, getCacheEntry, getLogger, invalidateHeadersCache, invalidateInvocationDefinitionsCache, setCacheEntry } from "@inkeep/agents-core";
3
+
4
+ //#region src/context/contextCache.ts
5
+ const logger = getLogger("context-cache");
6
+ /**
7
+ * Context cache with request hash-based invalidation and graceful error handling.
8
+ *
9
+ * Implements conversation-scoped caching with smart cache invalidation based on
10
+ * request hash changes. All cache errors are treated as cache misses to ensure
11
+ * system reliability.
12
+ */
13
+ var ContextCache = class {
14
+ executionContext;
15
+ constructor(executionContext) {
16
+ this.executionContext = executionContext;
17
+ logger.info({ tenantId: this.executionContext.tenantId }, "ContextCache initialized");
18
+ }
19
+ /**
20
+ * Get cached context data for a conversation
21
+ */
22
+ async get({ conversationId, contextConfigId, contextVariableKey, requestHash }) {
23
+ try {
24
+ let cacheEntry;
25
+ cacheEntry = await getCacheEntry(dbClient_default)({
26
+ conversationId,
27
+ contextConfigId,
28
+ contextVariableKey,
29
+ requestHash
30
+ });
31
+ if (!cacheEntry) return null;
32
+ return {
33
+ contextConfigId: cacheEntry.contextConfigId,
34
+ contextVariableKey: cacheEntry.contextVariableKey,
35
+ conversationId: cacheEntry.conversationId,
36
+ value: cacheEntry.value,
37
+ requestHash: cacheEntry.requestHash || void 0,
38
+ tenantId: this.executionContext.tenantId
39
+ };
40
+ } catch (error) {
41
+ logger.error({
42
+ conversationId,
43
+ contextConfigId,
44
+ contextVariableKey,
45
+ error: error instanceof Error ? error.message : "Unknown error"
46
+ }, "Failed to get cache entry");
47
+ return null;
48
+ }
49
+ }
50
+ /**
51
+ * Set cached context data for a conversation
52
+ */
53
+ async set(entry) {
54
+ try {
55
+ const { tenantId, projectId } = this.executionContext;
56
+ const cacheData = {
57
+ id: generateId(),
58
+ tenantId,
59
+ projectId,
60
+ conversationId: entry.conversationId,
61
+ contextConfigId: entry.contextConfigId,
62
+ contextVariableKey: entry.contextVariableKey,
63
+ value: entry.value,
64
+ requestHash: entry.requestHash,
65
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
66
+ fetchSource: `${entry.contextConfigId}:${entry.contextVariableKey}`,
67
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
68
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
69
+ ref: this.executionContext.resolvedRef
70
+ };
71
+ await setCacheEntry(dbClient_default)(cacheData);
72
+ logger.debug({
73
+ conversationId: entry.conversationId,
74
+ contextConfigId: entry.contextConfigId,
75
+ contextVariableKey: entry.contextVariableKey
76
+ }, "Cache entry set successfully");
77
+ } catch (error) {
78
+ logger.error({
79
+ conversationId: entry.conversationId,
80
+ contextConfigId: entry.contextConfigId,
81
+ contextVariableKey: entry.contextVariableKey,
82
+ error: error instanceof Error ? error.message : "Unknown error"
83
+ }, "Failed to set cache entry");
84
+ }
85
+ }
86
+ /**
87
+ * Clear cache entries for a specific conversation
88
+ */
89
+ async clearConversation(tenantId, projectId, conversationId) {
90
+ try {
91
+ let result;
92
+ result = await clearConversationCache(dbClient_default)({
93
+ scopes: {
94
+ tenantId,
95
+ projectId
96
+ },
97
+ conversationId
98
+ });
99
+ logger.info({
100
+ conversationId,
101
+ rowsCleared: result
102
+ }, "Conversation cache cleared successfully");
103
+ } catch (error) {
104
+ logger.error({
105
+ conversationId,
106
+ error: error instanceof Error ? error.message : "Unknown error"
107
+ }, "Failed to clear conversation cache");
108
+ throw error;
109
+ }
110
+ }
111
+ /**
112
+ * Clear all cache entries for a specific context configuration
113
+ */
114
+ async clearContextConfig(tenantId, projectId, contextConfigId) {
115
+ try {
116
+ const result = await clearContextConfigCache(dbClient_default)({
117
+ scopes: {
118
+ tenantId,
119
+ projectId
120
+ },
121
+ contextConfigId
122
+ });
123
+ logger.info({
124
+ contextConfigId,
125
+ rowsCleared: result
126
+ }, "Context config cache cleared successfully");
127
+ } catch (error) {
128
+ logger.error({
129
+ contextConfigId,
130
+ error: error instanceof Error ? error.message : "Unknown error"
131
+ }, "Failed to clear context config cache");
132
+ throw error;
133
+ }
134
+ }
135
+ /**
136
+ * Clean up expired or orphaned cache entries
137
+ */
138
+ async cleanup() {
139
+ try {
140
+ const { tenantId, projectId } = this.executionContext;
141
+ const result = await cleanupTenantCache(dbClient_default)({ scopes: {
142
+ tenantId,
143
+ projectId
144
+ } });
145
+ logger.info({ rowsCleared: result }, "Cache cleanup completed");
146
+ } catch (error) {
147
+ logger.error({ error: error instanceof Error ? error.message : "Unknown error" }, "Failed to cleanup cache");
148
+ throw error;
149
+ }
150
+ }
151
+ async invalidateInvocationDefinitions(tenantId, projectId, conversationId, contextConfigId, definitionIds) {
152
+ await invalidateInvocationDefinitionsCache(dbClient_default)({
153
+ scopes: {
154
+ tenantId,
155
+ projectId
156
+ },
157
+ conversationId,
158
+ contextConfigId,
159
+ invocationDefinitionIds: definitionIds
160
+ });
161
+ }
162
+ async invalidateHeaders(tenantId, projectId, conversationId, contextConfigId) {
163
+ await invalidateHeadersCache(dbClient_default)({
164
+ scopes: {
165
+ tenantId,
166
+ projectId
167
+ },
168
+ conversationId,
169
+ contextConfigId
170
+ });
171
+ }
172
+ };
173
+
174
+ //#endregion
175
+ export { ContextCache };
@@ -0,0 +1,6 @@
1
+ import { ContextFetcher, FetchResult, MissingRequiredVariableError } from "./ContextFetcher.js";
2
+ import { ContextResolutionOptions, ContextResolutionResult, ContextResolver, ResolvedContext } from "./ContextResolver.js";
3
+ import { determineContextTrigger, handleContextConfigChange, handleContextResolution } from "./context.js";
4
+ import { CacheEntry, ContextCache } from "./contextCache.js";
5
+ import { ContextValidationError, ContextValidationResult, HTTP_REQUEST_PARTS, HttpRequestPart, ParsedHttpRequest, contextValidationMiddleware, getCachedValidator, isValidHttpRequest, validateAgainstJsonSchema, validateHeaders, validateHttpRequestHeaders, validationHelper } from "./validation.js";
6
+ export { type CacheEntry, ContextCache, ContextFetcher, type ContextResolutionOptions, type ContextResolutionResult, ContextResolver, type ContextValidationError, type ContextValidationResult, type FetchResult, HTTP_REQUEST_PARTS, type HttpRequestPart, MissingRequiredVariableError, type ParsedHttpRequest, type ResolvedContext, contextValidationMiddleware, determineContextTrigger, getCachedValidator, handleContextConfigChange, handleContextResolution, isValidHttpRequest, validateAgainstJsonSchema, validateHeaders, validateHttpRequestHeaders, validationHelper };