@inkeep/agents-run-api 0.39.4 → 0.40.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 (180) hide show
  1. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/system-prompt.js +5 -0
  2. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/thinking-preparation.js +5 -0
  3. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/tool.js +5 -0
  4. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase2/data-component.js +5 -0
  5. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase2/data-components.js +5 -0
  6. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase2/system-prompt.js +5 -0
  7. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/shared/artifact-retrieval-guidance.js +5 -0
  8. package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/shared/artifact.js +5 -0
  9. package/dist/a2a/client.d.ts +184 -0
  10. package/dist/a2a/client.js +510 -0
  11. package/dist/a2a/handlers.d.ts +7 -0
  12. package/dist/a2a/handlers.js +560 -0
  13. package/dist/a2a/transfer.d.ts +22 -0
  14. package/dist/a2a/transfer.js +46 -0
  15. package/dist/a2a/types.d.ts +79 -0
  16. package/dist/a2a/types.js +22 -0
  17. package/dist/agents/Agent.d.ts +266 -0
  18. package/dist/agents/Agent.js +1927 -0
  19. package/dist/agents/ModelFactory.d.ts +63 -0
  20. package/dist/agents/ModelFactory.js +194 -0
  21. package/dist/agents/SystemPromptBuilder.d.ts +21 -0
  22. package/dist/agents/SystemPromptBuilder.js +48 -0
  23. package/dist/agents/ToolSessionManager.d.ts +63 -0
  24. package/dist/agents/ToolSessionManager.js +146 -0
  25. package/dist/agents/generateTaskHandler.d.ts +49 -0
  26. package/dist/agents/generateTaskHandler.js +521 -0
  27. package/dist/agents/relationTools.d.ts +57 -0
  28. package/dist/agents/relationTools.js +262 -0
  29. package/dist/agents/types.d.ts +28 -0
  30. package/dist/agents/types.js +1 -0
  31. package/dist/agents/versions/v1/Phase1Config.d.ts +27 -0
  32. package/dist/agents/versions/v1/Phase1Config.js +424 -0
  33. package/dist/agents/versions/v1/Phase2Config.d.ts +31 -0
  34. package/dist/agents/versions/v1/Phase2Config.js +330 -0
  35. package/dist/constants/execution-limits/defaults.d.ts +51 -0
  36. package/dist/constants/execution-limits/defaults.js +52 -0
  37. package/dist/constants/execution-limits/index.d.ts +6 -0
  38. package/dist/constants/execution-limits/index.js +21 -0
  39. package/dist/create-app.d.ts +9 -0
  40. package/dist/create-app.js +195 -0
  41. package/dist/data/agent.d.ts +7 -0
  42. package/dist/data/agent.js +72 -0
  43. package/dist/data/agents.d.ts +34 -0
  44. package/dist/data/agents.js +139 -0
  45. package/dist/data/conversations.d.ts +128 -0
  46. package/dist/data/conversations.js +522 -0
  47. package/dist/data/db/dbClient.d.ts +6 -0
  48. package/dist/data/db/dbClient.js +17 -0
  49. package/dist/env.d.ts +57 -0
  50. package/dist/env.js +1 -2
  51. package/dist/handlers/executionHandler.d.ts +39 -0
  52. package/dist/handlers/executionHandler.js +456 -0
  53. package/dist/index.d.ts +8 -29
  54. package/dist/index.js +5 -11235
  55. package/dist/instrumentation.d.ts +1 -2
  56. package/dist/instrumentation.js +66 -3
  57. package/dist/{logger2.js → logger.d.ts} +1 -2
  58. package/dist/logger.js +1 -1
  59. package/dist/middleware/api-key-auth.d.ts +26 -0
  60. package/dist/middleware/api-key-auth.js +240 -0
  61. package/dist/middleware/index.d.ts +2 -0
  62. package/dist/middleware/index.js +3 -0
  63. package/dist/openapi.d.ts +4 -0
  64. package/dist/openapi.js +54 -0
  65. package/dist/routes/agents.d.ts +12 -0
  66. package/dist/routes/agents.js +147 -0
  67. package/dist/routes/chat.d.ts +13 -0
  68. package/dist/routes/chat.js +293 -0
  69. package/dist/routes/chatDataStream.d.ts +13 -0
  70. package/dist/routes/chatDataStream.js +352 -0
  71. package/dist/routes/mcp.d.ts +13 -0
  72. package/dist/routes/mcp.js +495 -0
  73. package/dist/services/AgentSession.d.ts +356 -0
  74. package/dist/services/AgentSession.js +1208 -0
  75. package/dist/services/ArtifactParser.d.ts +105 -0
  76. package/dist/services/ArtifactParser.js +338 -0
  77. package/dist/services/ArtifactService.d.ts +123 -0
  78. package/dist/services/ArtifactService.js +612 -0
  79. package/dist/services/BaseCompressor.d.ts +183 -0
  80. package/dist/services/BaseCompressor.js +504 -0
  81. package/dist/services/ConversationCompressor.d.ts +32 -0
  82. package/dist/services/ConversationCompressor.js +91 -0
  83. package/dist/services/IncrementalStreamParser.d.ts +98 -0
  84. package/dist/services/IncrementalStreamParser.js +327 -0
  85. package/dist/services/MidGenerationCompressor.d.ts +63 -0
  86. package/dist/services/MidGenerationCompressor.js +104 -0
  87. package/dist/services/PendingToolApprovalManager.d.ts +62 -0
  88. package/dist/services/PendingToolApprovalManager.js +133 -0
  89. package/dist/services/ResponseFormatter.d.ts +39 -0
  90. package/dist/services/ResponseFormatter.js +152 -0
  91. package/dist/tools/NativeSandboxExecutor.d.ts +38 -0
  92. package/dist/tools/NativeSandboxExecutor.js +432 -0
  93. package/dist/tools/SandboxExecutorFactory.d.ts +36 -0
  94. package/dist/tools/SandboxExecutorFactory.js +80 -0
  95. package/dist/tools/VercelSandboxExecutor.d.ts +71 -0
  96. package/dist/tools/VercelSandboxExecutor.js +340 -0
  97. package/dist/tools/distill-conversation-history-tool.d.ts +62 -0
  98. package/dist/tools/distill-conversation-history-tool.js +206 -0
  99. package/dist/tools/distill-conversation-tool.d.ts +41 -0
  100. package/dist/tools/distill-conversation-tool.js +141 -0
  101. package/dist/tools/sandbox-utils.d.ts +18 -0
  102. package/dist/tools/sandbox-utils.js +53 -0
  103. package/dist/types/chat.d.ts +27 -0
  104. package/dist/types/chat.js +1 -0
  105. package/dist/types/execution-context.d.ts +46 -0
  106. package/dist/types/execution-context.js +27 -0
  107. package/dist/types/xml.d.ts +5 -0
  108. package/dist/utils/SchemaProcessor.d.ts +52 -0
  109. package/dist/utils/SchemaProcessor.js +182 -0
  110. package/dist/utils/agent-operations.d.ts +62 -0
  111. package/dist/utils/agent-operations.js +53 -0
  112. package/dist/utils/artifact-component-schema.d.ts +42 -0
  113. package/dist/utils/artifact-component-schema.js +186 -0
  114. package/dist/utils/cleanup.d.ts +21 -0
  115. package/dist/utils/cleanup.js +59 -0
  116. package/dist/utils/data-component-schema.d.ts +2 -0
  117. package/dist/utils/data-component-schema.js +3 -0
  118. package/dist/utils/default-status-schemas.d.ts +20 -0
  119. package/dist/utils/default-status-schemas.js +24 -0
  120. package/dist/utils/json-postprocessor.d.ts +13 -0
  121. package/dist/{json-postprocessor.cjs → utils/json-postprocessor.js} +1 -2
  122. package/dist/utils/model-context-utils.d.ts +39 -0
  123. package/dist/utils/model-context-utils.js +181 -0
  124. package/dist/utils/model-resolver.d.ts +6 -0
  125. package/dist/utils/model-resolver.js +34 -0
  126. package/dist/utils/schema-validation.d.ts +44 -0
  127. package/dist/utils/schema-validation.js +97 -0
  128. package/dist/utils/stream-helpers.d.ts +197 -0
  129. package/dist/utils/stream-helpers.js +518 -0
  130. package/dist/utils/stream-registry.d.ts +22 -0
  131. package/dist/utils/stream-registry.js +34 -0
  132. package/dist/utils/token-estimator.d.ts +69 -0
  133. package/dist/utils/token-estimator.js +53 -0
  134. package/dist/utils/tracer.d.ts +7 -0
  135. package/dist/utils/tracer.js +7 -0
  136. package/package.json +5 -20
  137. package/dist/SandboxExecutorFactory.cjs +0 -895
  138. package/dist/SandboxExecutorFactory.js +0 -893
  139. package/dist/SandboxExecutorFactory.js.map +0 -1
  140. package/dist/chunk-VBDAOXYI.cjs +0 -927
  141. package/dist/chunk-VBDAOXYI.js +0 -832
  142. package/dist/chunk-VBDAOXYI.js.map +0 -1
  143. package/dist/chunk.cjs +0 -34
  144. package/dist/conversations.cjs +0 -7
  145. package/dist/conversations.js +0 -7
  146. package/dist/conversations2.cjs +0 -209
  147. package/dist/conversations2.js +0 -180
  148. package/dist/conversations2.js.map +0 -1
  149. package/dist/dbClient.cjs +0 -9676
  150. package/dist/dbClient.js +0 -9670
  151. package/dist/dbClient.js.map +0 -1
  152. package/dist/dbClient2.cjs +0 -5
  153. package/dist/dbClient2.js +0 -5
  154. package/dist/env.cjs +0 -59
  155. package/dist/env.js.map +0 -1
  156. package/dist/execution-limits.cjs +0 -260
  157. package/dist/execution-limits.js +0 -63
  158. package/dist/execution-limits.js.map +0 -1
  159. package/dist/index.cjs +0 -11260
  160. package/dist/index.d.cts +0 -36
  161. package/dist/index.d.cts.map +0 -1
  162. package/dist/index.d.ts.map +0 -1
  163. package/dist/index.js.map +0 -1
  164. package/dist/instrumentation.cjs +0 -12
  165. package/dist/instrumentation.d.cts +0 -18
  166. package/dist/instrumentation.d.cts.map +0 -1
  167. package/dist/instrumentation.d.ts.map +0 -1
  168. package/dist/instrumentation2.cjs +0 -116
  169. package/dist/instrumentation2.js +0 -69
  170. package/dist/instrumentation2.js.map +0 -1
  171. package/dist/json-postprocessor.js +0 -20
  172. package/dist/json-postprocessor.js.map +0 -1
  173. package/dist/logger.cjs +0 -5
  174. package/dist/logger2.cjs +0 -1
  175. package/dist/nodefs.cjs +0 -29
  176. package/dist/nodefs.js +0 -27
  177. package/dist/nodefs.js.map +0 -1
  178. package/dist/opfs-ahp.cjs +0 -367
  179. package/dist/opfs-ahp.js +0 -368
  180. package/dist/opfs-ahp.js.map +0 -1
@@ -0,0 +1,612 @@
1
+ import { getLogger } from "../logger.js";
2
+ import dbClient_default from "../data/db/dbClient.js";
3
+ import { toolSessionManager } from "../agents/ToolSessionManager.js";
4
+ import { extractFullFields, extractPreviewFields } from "../utils/schema-validation.js";
5
+ import { agentSessionManager } from "./AgentSession.js";
6
+ import { getLedgerArtifacts, getTask, listTaskIdsByContextId, upsertLedgerArtifact } from "@inkeep/agents-core";
7
+ import jmespath from "jmespath";
8
+
9
+ //#region src/services/ArtifactService.ts
10
+ const logger = getLogger("ArtifactService");
11
+ /**
12
+ * Service class responsible for artifact business logic operations
13
+ * Handles database persistence, tool result extraction, and artifact management
14
+ * Separated from parsing concerns for better architecture
15
+ */
16
+ var ArtifactService = class ArtifactService {
17
+ createdArtifacts = /* @__PURE__ */ new Map();
18
+ static selectorCache = /* @__PURE__ */ new Map();
19
+ constructor(context) {
20
+ this.context = context;
21
+ }
22
+ /**
23
+ * Clear static caches to prevent memory leaks between sessions
24
+ */
25
+ static clearCaches() {
26
+ ArtifactService.selectorCache.clear();
27
+ }
28
+ /**
29
+ * Update artifact components in the context
30
+ */
31
+ updateArtifactComponents(artifactComponents) {
32
+ this.context.artifactComponents = artifactComponents;
33
+ }
34
+ /**
35
+ * Get all artifacts for a context from database
36
+ */
37
+ async getContextArtifacts(contextId) {
38
+ const artifacts = /* @__PURE__ */ new Map();
39
+ try {
40
+ const taskIds = await listTaskIdsByContextId(dbClient_default)({ contextId });
41
+ for (const taskId of taskIds) {
42
+ const task = await getTask(dbClient_default)({ id: taskId });
43
+ if (!task) {
44
+ logger.warn({ taskId }, "Task not found when fetching artifacts");
45
+ continue;
46
+ }
47
+ const taskArtifacts = await getLedgerArtifacts(dbClient_default)({
48
+ scopes: {
49
+ tenantId: this.context.tenantId,
50
+ projectId: task.projectId
51
+ },
52
+ taskId
53
+ });
54
+ for (const artifact of taskArtifacts) {
55
+ const toolCallId = artifact.metadata?.toolCallId || "";
56
+ if (toolCallId) {
57
+ const key = `${artifact.artifactId}:${toolCallId}`;
58
+ artifacts.set(key, artifact);
59
+ }
60
+ const taskKey = `${artifact.artifactId}:${artifact.taskId}`;
61
+ artifacts.set(taskKey, artifact);
62
+ }
63
+ }
64
+ } catch (error) {
65
+ logger.error({
66
+ error,
67
+ contextId
68
+ }, "Error loading context artifacts");
69
+ }
70
+ return artifacts;
71
+ }
72
+ /**
73
+ * Create artifact from tool result and request data
74
+ */
75
+ async createArtifact(request, subAgentId) {
76
+ if (!this.context.sessionId) {
77
+ logger.warn({ request }, "No session ID available for artifact creation");
78
+ return null;
79
+ }
80
+ const toolResult = toolSessionManager.getToolResult(this.context.sessionId, request.toolCallId);
81
+ if (!toolResult) {
82
+ logger.warn({
83
+ request,
84
+ sessionId: this.context.sessionId
85
+ }, "Tool result not found for artifact");
86
+ return null;
87
+ }
88
+ try {
89
+ const toolResultData = toolResult && typeof toolResult === "object" && !Array.isArray(toolResult) ? Object.fromEntries(Object.entries(toolResult).filter(([key]) => key !== "_structureHints")) : toolResult;
90
+ const sanitizedBaseSelector = this.sanitizeJMESPathSelector(request.baseSelector);
91
+ let selectedData = jmespath.search(toolResultData, sanitizedBaseSelector);
92
+ if (Array.isArray(selectedData)) selectedData = selectedData.length > 0 ? selectedData[0] : {};
93
+ if (!selectedData) {
94
+ logger.warn({
95
+ request,
96
+ baseSelector: request.baseSelector
97
+ }, "Base selector returned no data - using empty object as fallback");
98
+ selectedData = {};
99
+ }
100
+ const component = this.context.artifactComponents?.find((ac) => ac.name === request.type);
101
+ let summaryData = {};
102
+ let fullData = {};
103
+ let previewSchema = null;
104
+ let fullSchema = null;
105
+ if (component?.props) {
106
+ previewSchema = extractPreviewFields(component.props);
107
+ fullSchema = extractFullFields(component.props);
108
+ summaryData = this.extractPropsFromSchema(selectedData, previewSchema, request.detailsSelector || {});
109
+ fullData = this.extractPropsFromSchema(selectedData, fullSchema, request.detailsSelector || {});
110
+ } else {
111
+ summaryData = selectedData;
112
+ fullData = selectedData;
113
+ }
114
+ if (!fullData || Object.keys(fullData).length === 0 || Object.values(fullData).every((val) => val === null || val === void 0 || val === "" || Array.isArray(val) && val.length === 0 || typeof val === "object" && Object.keys(val).length === 0)) fullData = { baseSelector: selectedData };
115
+ const cleanedSummaryData = this.cleanEscapedContent(summaryData);
116
+ const cleanedFullData = this.cleanEscapedContent(fullData);
117
+ const schemaValidation = this.validateExtractedData(request.artifactId, request.type, cleanedSummaryData, cleanedFullData, previewSchema, fullSchema, component?.props);
118
+ const artifactData = {
119
+ artifactId: request.artifactId,
120
+ toolCallId: request.toolCallId,
121
+ name: "Processing...",
122
+ description: "Name and description being generated...",
123
+ type: request.type,
124
+ data: cleanedSummaryData
125
+ };
126
+ await this.persistArtifact(request, cleanedSummaryData, cleanedFullData, subAgentId, schemaValidation);
127
+ await this.cacheArtifact(request.artifactId, request.toolCallId, artifactData, cleanedFullData);
128
+ return artifactData;
129
+ } catch (error) {
130
+ logger.error({
131
+ error,
132
+ request
133
+ }, "Failed to create artifact");
134
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
135
+ throw new Error(`Artifact creation failed for ${request.artifactId}: ${errorMessage}`);
136
+ }
137
+ }
138
+ /**
139
+ * Get artifact summary data by ID and tool call ID
140
+ */
141
+ async getArtifactSummary(artifactId, toolCallId, artifactMap) {
142
+ const key = `${artifactId}:${toolCallId}`;
143
+ if (this.context.streamRequestId) {
144
+ const cachedArtifact = await agentSessionManager.getArtifactCache(this.context.streamRequestId, key);
145
+ if (cachedArtifact) return this.formatArtifactSummaryData(cachedArtifact, artifactId, toolCallId);
146
+ }
147
+ if (this.createdArtifacts.has(key)) {
148
+ const cached = this.createdArtifacts.get(key);
149
+ return this.formatArtifactSummaryData(cached, artifactId, toolCallId);
150
+ }
151
+ if (artifactMap?.has(key)) {
152
+ const artifact = artifactMap.get(key);
153
+ return this.formatArtifactSummaryData(artifact, artifactId, toolCallId);
154
+ }
155
+ try {
156
+ if (!this.context.projectId || !this.context.taskId) {
157
+ logger.warn({
158
+ artifactId,
159
+ toolCallId
160
+ }, "No projectId or taskId available for artifact lookup");
161
+ return null;
162
+ }
163
+ let artifacts = [];
164
+ artifacts = await getLedgerArtifacts(dbClient_default)({
165
+ scopes: {
166
+ tenantId: this.context.tenantId,
167
+ projectId: this.context.projectId
168
+ },
169
+ artifactId,
170
+ toolCallId
171
+ });
172
+ if (artifacts.length > 0) return this.formatArtifactSummaryData(artifacts[0], artifactId, toolCallId);
173
+ artifacts = await getLedgerArtifacts(dbClient_default)({
174
+ scopes: {
175
+ tenantId: this.context.tenantId,
176
+ projectId: this.context.projectId
177
+ },
178
+ artifactId,
179
+ taskId: this.context.taskId
180
+ });
181
+ if (artifacts.length > 0) return this.formatArtifactSummaryData(artifacts[0], artifactId, toolCallId);
182
+ } catch (error) {
183
+ logger.warn({
184
+ artifactId,
185
+ toolCallId,
186
+ taskId: this.context.taskId,
187
+ error
188
+ }, "Failed to fetch artifact");
189
+ }
190
+ return null;
191
+ }
192
+ /**
193
+ * Get artifact full data by ID and tool call ID
194
+ */
195
+ async getArtifactFull(artifactId, toolCallId, artifactMap) {
196
+ const key = `${artifactId}:${toolCallId}`;
197
+ if (this.context.streamRequestId) {
198
+ const cachedArtifact = await agentSessionManager.getArtifactCache(this.context.streamRequestId, key);
199
+ if (cachedArtifact) return this.formatArtifactFullData(cachedArtifact, artifactId, toolCallId);
200
+ }
201
+ if (this.createdArtifacts.has(key)) {
202
+ const cached = this.createdArtifacts.get(key);
203
+ return this.formatArtifactFullData(cached, artifactId, toolCallId);
204
+ }
205
+ if (artifactMap?.has(key)) {
206
+ const artifact = artifactMap.get(key);
207
+ return this.formatArtifactFullData(artifact, artifactId, toolCallId);
208
+ }
209
+ try {
210
+ if (!this.context.projectId || !this.context.taskId) {
211
+ logger.warn({
212
+ artifactId,
213
+ toolCallId
214
+ }, "No projectId or taskId available for artifact lookup");
215
+ return null;
216
+ }
217
+ let artifacts = [];
218
+ artifacts = await getLedgerArtifacts(dbClient_default)({
219
+ scopes: {
220
+ tenantId: this.context.tenantId,
221
+ projectId: this.context.projectId
222
+ },
223
+ artifactId,
224
+ toolCallId
225
+ });
226
+ if (artifacts.length > 0) return this.formatArtifactFullData(artifacts[0], artifactId, toolCallId);
227
+ artifacts = await getLedgerArtifacts(dbClient_default)({
228
+ scopes: {
229
+ tenantId: this.context.tenantId,
230
+ projectId: this.context.projectId
231
+ },
232
+ artifactId,
233
+ taskId: this.context.taskId
234
+ });
235
+ if (artifacts.length > 0) return this.formatArtifactFullData(artifacts[0], artifactId, toolCallId);
236
+ } catch (error) {
237
+ logger.warn({
238
+ artifactId,
239
+ toolCallId,
240
+ taskId: this.context.taskId,
241
+ error
242
+ }, "Failed to fetch artifact");
243
+ }
244
+ return null;
245
+ }
246
+ /**
247
+ * Format raw artifact to standardized summary data format
248
+ */
249
+ formatArtifactSummaryData(artifact, artifactId, toolCallId) {
250
+ let data = artifact.parts?.[0]?.data?.summary;
251
+ let dataSource = "parts[0].data.summary";
252
+ if (!data || typeof data === "object" && Object.keys(data).length === 0) {
253
+ data = artifact.parts?.[0]?.data;
254
+ if (data && !(typeof data === "object" && Object.keys(data).length === 0)) {
255
+ dataSource = "parts[0].data (fallback)";
256
+ logger.debug({
257
+ artifactId,
258
+ toolCallId,
259
+ dataSource
260
+ }, "Using fallback data source for artifact summary");
261
+ } else {
262
+ data = artifact.data;
263
+ if (data && !(typeof data === "object" && Object.keys(data).length === 0)) {
264
+ dataSource = "artifact.data (fallback)";
265
+ logger.debug({
266
+ artifactId,
267
+ toolCallId,
268
+ dataSource
269
+ }, "Using fallback data source for artifact summary");
270
+ } else {
271
+ data = {};
272
+ dataSource = "empty (no data found)";
273
+ logger.warn({
274
+ artifactId,
275
+ toolCallId,
276
+ artifactStructure: {
277
+ hasParts: !!artifact.parts,
278
+ partsLength: artifact.parts?.length,
279
+ hasPartsData: !!artifact.parts?.[0]?.data,
280
+ hasPartsSummary: !!artifact.parts?.[0]?.data?.summary,
281
+ hasArtifactData: !!artifact.data,
282
+ artifactKeys: Object.keys(artifact || {})
283
+ }
284
+ }, "No valid data found for artifact summary - using empty object");
285
+ }
286
+ }
287
+ }
288
+ return {
289
+ artifactId,
290
+ toolCallId,
291
+ name: artifact.name || "Processing...",
292
+ description: artifact.description || "Name and description being generated...",
293
+ type: artifact.metadata?.artifactType || artifact.artifactType,
294
+ data
295
+ };
296
+ }
297
+ /**
298
+ * Format raw artifact to standardized full data format
299
+ */
300
+ formatArtifactFullData(artifact, artifactId, toolCallId) {
301
+ let data = artifact.parts?.[0]?.data?.full;
302
+ let dataSource = "parts[0].data.full";
303
+ if (!data || typeof data === "object" && Object.keys(data).length === 0) {
304
+ data = artifact.parts?.[0]?.data;
305
+ if (data && !(typeof data === "object" && Object.keys(data).length === 0)) {
306
+ dataSource = "parts[0].data (fallback)";
307
+ logger.debug({
308
+ artifactId,
309
+ toolCallId,
310
+ dataSource
311
+ }, "Using fallback data source for artifact full data");
312
+ } else {
313
+ data = artifact.data;
314
+ if (data && !(typeof data === "object" && Object.keys(data).length === 0)) {
315
+ dataSource = "artifact.data (fallback)";
316
+ logger.debug({
317
+ artifactId,
318
+ toolCallId,
319
+ dataSource
320
+ }, "Using fallback data source for artifact full data");
321
+ } else {
322
+ data = {};
323
+ dataSource = "empty (no data found)";
324
+ logger.warn({
325
+ artifactId,
326
+ toolCallId,
327
+ artifactStructure: {
328
+ hasParts: !!artifact.parts,
329
+ partsLength: artifact.parts?.length,
330
+ hasPartsData: !!artifact.parts?.[0]?.data,
331
+ hasPartsFull: !!artifact.parts?.[0]?.data?.full,
332
+ hasArtifactData: !!artifact.data,
333
+ artifactKeys: Object.keys(artifact || {})
334
+ }
335
+ }, "No valid data found for artifact full data - using empty object");
336
+ }
337
+ }
338
+ }
339
+ return {
340
+ artifactId,
341
+ toolCallId,
342
+ name: artifact.name || "Processing...",
343
+ description: artifact.description || "Name and description being generated...",
344
+ type: artifact.metadata?.artifactType || artifact.artifactType,
345
+ data
346
+ };
347
+ }
348
+ /**
349
+ * Validate extracted data against the schemas used for extraction
350
+ */
351
+ validateExtractedData(artifactId, artifactType, summaryData, fullData, previewSchema, fullSchema, originalProps) {
352
+ const validateAgainstSchema = (data, schema) => {
353
+ const actualFields = Object.keys(data || {});
354
+ const expectedFields = schema?.properties ? Object.keys(schema.properties) : [];
355
+ const missingFields = expectedFields.filter((field) => !(field in (data || {})));
356
+ const extraFields = actualFields.filter((field) => !expectedFields.includes(field));
357
+ const missingRequired = (schema?.required || []).filter((field) => !(field in (data || {})));
358
+ return {
359
+ hasExpectedFields: missingFields.length === 0,
360
+ missingFields,
361
+ extraFields,
362
+ expectedFields,
363
+ actualFields,
364
+ hasRequiredFields: missingRequired.length === 0,
365
+ missingRequired
366
+ };
367
+ };
368
+ const summaryValidation = validateAgainstSchema(summaryData, previewSchema);
369
+ const fullValidation = validateAgainstSchema(fullData, fullSchema);
370
+ if (!summaryValidation.hasRequiredFields) {
371
+ `${summaryValidation.missingRequired.join(", ")}${artifactType}${summaryValidation.missingRequired.join(", ")}${summaryValidation.actualFields.join(", ")}`;
372
+ logger.error({
373
+ artifactId,
374
+ artifactType,
375
+ requiredFields: summaryValidation.missingRequired,
376
+ actualFields: summaryValidation.actualFields,
377
+ schemaExpected: previewSchema?.properties ? Object.keys(previewSchema.properties) : []
378
+ }, "Artifact creation failed due to missing required fields - continuing with generation");
379
+ return {
380
+ summary: summaryValidation,
381
+ full: fullValidation,
382
+ schemaFound: !!previewSchema
383
+ };
384
+ }
385
+ if (!summaryValidation.hasExpectedFields || summaryValidation.extraFields.length > 0) logger.warn({
386
+ artifactId,
387
+ artifactType,
388
+ dataType: "summary",
389
+ expectedFields: summaryValidation.expectedFields,
390
+ actualFields: summaryValidation.actualFields,
391
+ missingFields: summaryValidation.missingFields,
392
+ extraFields: summaryValidation.extraFields
393
+ }, "Summary data structure does not match preview schema");
394
+ if (!fullValidation.hasExpectedFields || fullValidation.extraFields.length > 0) logger.warn({
395
+ artifactId,
396
+ artifactType,
397
+ dataType: "full",
398
+ expectedFields: fullValidation.expectedFields,
399
+ actualFields: fullValidation.actualFields,
400
+ missingFields: fullValidation.missingFields,
401
+ extraFields: fullValidation.extraFields
402
+ }, "Full data structure does not match full schema");
403
+ return {
404
+ summary: summaryValidation,
405
+ full: fullValidation,
406
+ schemaFound: !!originalProps
407
+ };
408
+ }
409
+ /**
410
+ * Persist artifact to database vian agent session
411
+ */
412
+ async persistArtifact(request, summaryData, fullData, subAgentId, schemaValidation) {
413
+ const effectiveAgentId = subAgentId || this.context.subAgentId;
414
+ if (this.context.streamRequestId && effectiveAgentId && this.context.taskId) await agentSessionManager.recordEvent(this.context.streamRequestId, "artifact_saved", effectiveAgentId, {
415
+ artifactId: request.artifactId,
416
+ taskId: this.context.taskId,
417
+ toolCallId: request.toolCallId,
418
+ artifactType: request.type,
419
+ summaryData,
420
+ data: fullData,
421
+ subAgentId: effectiveAgentId,
422
+ metadata: {
423
+ toolCallId: request.toolCallId,
424
+ baseSelector: request.baseSelector,
425
+ detailsSelector: request.detailsSelector,
426
+ sessionId: this.context.sessionId,
427
+ artifactType: request.type
428
+ },
429
+ schemaValidation: schemaValidation || {
430
+ summary: {
431
+ hasExpectedFields: true,
432
+ missingFields: [],
433
+ extraFields: [],
434
+ expectedFields: [],
435
+ actualFields: [],
436
+ hasRequiredFields: true,
437
+ missingRequired: []
438
+ },
439
+ full: {
440
+ hasExpectedFields: true,
441
+ missingFields: [],
442
+ extraFields: [],
443
+ expectedFields: [],
444
+ actualFields: [],
445
+ hasRequiredFields: true,
446
+ missingRequired: []
447
+ },
448
+ schemaFound: false
449
+ },
450
+ tenantId: this.context.tenantId,
451
+ projectId: this.context.projectId,
452
+ contextId: this.context.contextId,
453
+ pendingGeneration: true
454
+ });
455
+ else logger.warn({
456
+ artifactId: request.artifactId,
457
+ hasStreamRequestId: !!this.context.streamRequestId,
458
+ hasAgentId: !!effectiveAgentId,
459
+ hasTaskId: !!this.context.taskId,
460
+ passedAgentId: subAgentId,
461
+ contextAgentId: this.context.subAgentId
462
+ }, "Skipping artifact_saved event - missing required context");
463
+ }
464
+ /**
465
+ * Cache artifact for immediate access
466
+ */
467
+ async cacheArtifact(artifactId, toolCallId, artifactData, fullData) {
468
+ const cacheKey = `${artifactId}:${toolCallId}`;
469
+ const artifactForCache = {
470
+ ...artifactData,
471
+ parts: [{ data: {
472
+ summary: artifactData.data,
473
+ data: fullData
474
+ } }],
475
+ metadata: {
476
+ artifactType: artifactData.type,
477
+ toolCallId
478
+ },
479
+ taskId: this.context.taskId
480
+ };
481
+ this.createdArtifacts.set(cacheKey, artifactForCache);
482
+ if (this.context.streamRequestId) await agentSessionManager.setArtifactCache(this.context.streamRequestId, cacheKey, artifactForCache);
483
+ }
484
+ /**
485
+ * Sanitize JMESPath selector to fix common syntax issues (with caching)
486
+ */
487
+ sanitizeJMESPathSelector(selector) {
488
+ const cached = ArtifactService.selectorCache.get(selector);
489
+ if (cached !== void 0) return cached;
490
+ let sanitized = selector.replace(/=="([^"]*)"/g, "=='$1'");
491
+ sanitized = sanitized.replace(/\[\?(\w+)\s*~\s*contains\(@,\s*"([^"]*)"\)\]/g, "[?contains($1, `$2`)]");
492
+ sanitized = sanitized.replace(/\[\?(\w+)\s*~\s*contains\(@,\s*'([^']*)'\)\]/g, "[?contains($1, `$2`)]");
493
+ sanitized = sanitized.replace(/\s*~\s*/g, " ");
494
+ if (ArtifactService.selectorCache.size < 1e3) ArtifactService.selectorCache.set(selector, sanitized);
495
+ return sanitized;
496
+ }
497
+ /**
498
+ * Save an already-created artifact directly to the database
499
+ * Used by AgentSession to save artifacts after name/description generation
500
+ */
501
+ async saveArtifact(artifact) {
502
+ let summaryData = artifact.summaryData || artifact.data;
503
+ let fullData = artifact.data;
504
+ if (this.context.artifactComponents) {
505
+ const artifactComponent = this.context.artifactComponents.find((ac) => ac.name === artifact.type);
506
+ if (artifactComponent?.props) try {
507
+ const schema = artifactComponent.props;
508
+ const previewSchema = extractPreviewFields(schema);
509
+ const fullSchema = extractFullFields(schema);
510
+ summaryData = this.filterBySchema(artifact.data, previewSchema);
511
+ fullData = this.filterBySchema(artifact.data, fullSchema);
512
+ } catch (error) {
513
+ logger.warn({
514
+ artifactType: artifact.type,
515
+ error: error instanceof Error ? error.message : "Unknown error"
516
+ }, "Failed to extract preview/full fields from schema, using full data for both");
517
+ }
518
+ }
519
+ const artifactToSave = {
520
+ artifactId: artifact.artifactId,
521
+ name: artifact.name,
522
+ description: artifact.description,
523
+ type: artifact.type,
524
+ taskId: this.context.taskId,
525
+ parts: [{
526
+ kind: "data",
527
+ data: {
528
+ summary: summaryData,
529
+ full: fullData
530
+ }
531
+ }],
532
+ metadata: artifact.metadata || {},
533
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
534
+ };
535
+ const result = await upsertLedgerArtifact(dbClient_default)({
536
+ scopes: {
537
+ tenantId: this.context.tenantId,
538
+ projectId: this.context.projectId
539
+ },
540
+ contextId: this.context.contextId,
541
+ taskId: this.context.taskId,
542
+ toolCallId: artifact.toolCallId,
543
+ artifact: artifactToSave
544
+ });
545
+ if (!result.created && result.existing) logger.debug({
546
+ artifactId: artifact.artifactId,
547
+ taskId: this.context.taskId
548
+ }, "Artifact already exists, skipping duplicate creation");
549
+ }
550
+ /**
551
+ * Clean up over-escaped strings that have been through multiple JSON serialization cycles
552
+ */
553
+ cleanEscapedContent(value) {
554
+ if (typeof value === "string") {
555
+ let cleaned = value;
556
+ cleaned = cleaned.replace(/\u0000/g, "").replace(/[\u0001-\u0008\u000B\u000C\u000E-\u001F]/g, "");
557
+ cleaned = cleaned.replace(/\\"([^"]+)\\"/g, "\"$1\"").replace(/\\'/g, "'").replace(/\\`/g, "`").replace(/\\\\/g, "\\");
558
+ const maxIterations = 10;
559
+ let iteration = 0;
560
+ let previousLength;
561
+ do {
562
+ previousLength = cleaned.length;
563
+ cleaned = cleaned.replace(/\\\\\\\\n/g, "\n").replace(/\\\\\\\\/g, "\\").replace(/\\\\n/g, "\n").replace(/\\\\/g, "\\").replace(/\\n/g, "\n").replace(/\\"/g, "\"").replace(/\\'/g, "'");
564
+ iteration++;
565
+ } while (cleaned.length !== previousLength && iteration < maxIterations);
566
+ cleaned = cleaned.replace(/\\\\/g, "\\");
567
+ return cleaned;
568
+ }
569
+ if (Array.isArray(value)) return value.map((item) => this.cleanEscapedContent(item));
570
+ if (value && typeof value === "object") {
571
+ const cleaned = {};
572
+ for (const [key, val] of Object.entries(value)) cleaned[key] = this.cleanEscapedContent(val);
573
+ return cleaned;
574
+ }
575
+ return value;
576
+ }
577
+ /**
578
+ * Extract properties from data using schema-defined fields and custom selectors
579
+ */
580
+ extractPropsFromSchema(item, schema, customSelectors) {
581
+ const extracted = {};
582
+ if (schema.properties) for (const fieldName of Object.keys(schema.properties)) try {
583
+ const customSelector = customSelectors[fieldName];
584
+ let rawValue;
585
+ if (customSelector) {
586
+ const sanitizedSelector = this.sanitizeJMESPathSelector(customSelector);
587
+ rawValue = jmespath.search(item, sanitizedSelector);
588
+ } else rawValue = item[fieldName];
589
+ if (rawValue !== null && rawValue !== void 0) extracted[fieldName] = this.cleanEscapedContent(rawValue);
590
+ } catch (error) {
591
+ logger.warn({
592
+ fieldName,
593
+ error: error instanceof Error ? error.message : "Unknown error"
594
+ }, "Failed to extract schema field");
595
+ const fallbackValue = item[fieldName];
596
+ if (fallbackValue !== null && fallbackValue !== void 0) extracted[fieldName] = this.cleanEscapedContent(fallbackValue);
597
+ }
598
+ return extracted;
599
+ }
600
+ /**
601
+ * Filter extracted props based on schema
602
+ */
603
+ filterBySchema(props, schema) {
604
+ if (!schema?.properties) return props;
605
+ const filtered = {};
606
+ for (const key of Object.keys(schema.properties)) if (key in props) filtered[key] = props[key];
607
+ return filtered;
608
+ }
609
+ };
610
+
611
+ //#endregion
612
+ export { ArtifactService };