@inkeep/agents-run-api 0.39.5 → 0.41.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.
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/system-prompt.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/thinking-preparation.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/tool.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase2/data-component.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase2/data-components.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase2/system-prompt.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/shared/artifact-retrieval-guidance.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/shared/artifact.js +5 -0
- package/dist/a2a/client.d.ts +184 -0
- package/dist/a2a/client.js +510 -0
- package/dist/a2a/handlers.d.ts +7 -0
- package/dist/a2a/handlers.js +576 -0
- package/dist/a2a/transfer.d.ts +22 -0
- package/dist/a2a/transfer.js +46 -0
- package/dist/a2a/types.d.ts +79 -0
- package/dist/a2a/types.js +22 -0
- package/dist/agents/Agent.d.ts +268 -0
- package/dist/agents/Agent.js +1932 -0
- package/dist/agents/ModelFactory.d.ts +63 -0
- package/dist/agents/ModelFactory.js +194 -0
- package/dist/agents/SystemPromptBuilder.d.ts +21 -0
- package/dist/agents/SystemPromptBuilder.js +48 -0
- package/dist/agents/ToolSessionManager.d.ts +63 -0
- package/dist/agents/ToolSessionManager.js +146 -0
- package/dist/agents/generateTaskHandler.d.ts +49 -0
- package/dist/agents/generateTaskHandler.js +523 -0
- package/dist/agents/relationTools.d.ts +57 -0
- package/dist/agents/relationTools.js +262 -0
- package/dist/agents/types.d.ts +28 -0
- package/dist/agents/types.js +1 -0
- package/dist/agents/versions/v1/Phase1Config.d.ts +27 -0
- package/dist/agents/versions/v1/Phase1Config.js +424 -0
- package/dist/agents/versions/v1/Phase2Config.d.ts +31 -0
- package/dist/agents/versions/v1/Phase2Config.js +330 -0
- package/dist/constants/execution-limits/defaults.d.ts +51 -0
- package/dist/constants/execution-limits/defaults.js +52 -0
- package/dist/constants/execution-limits/index.d.ts +6 -0
- package/dist/constants/execution-limits/index.js +21 -0
- package/dist/create-app.d.ts +9 -0
- package/dist/create-app.js +195 -0
- package/dist/data/agent.d.ts +7 -0
- package/dist/data/agent.js +72 -0
- package/dist/data/agents.d.ts +34 -0
- package/dist/data/agents.js +139 -0
- package/dist/data/conversations.d.ts +128 -0
- package/dist/data/conversations.js +522 -0
- package/dist/data/db/dbClient.d.ts +6 -0
- package/dist/data/db/dbClient.js +17 -0
- package/dist/env.d.ts +57 -0
- package/dist/env.js +1 -2
- package/dist/handlers/executionHandler.d.ts +41 -0
- package/dist/handlers/executionHandler.js +457 -0
- package/dist/index.d.ts +8 -29
- package/dist/index.js +5 -11386
- package/dist/instrumentation.d.ts +1 -2
- package/dist/instrumentation.js +66 -3
- package/dist/{logger2.js → logger.d.ts} +1 -2
- package/dist/logger.js +1 -1
- package/dist/middleware/api-key-auth.d.ts +26 -0
- package/dist/middleware/api-key-auth.js +240 -0
- package/dist/middleware/index.d.ts +2 -0
- package/dist/middleware/index.js +3 -0
- package/dist/openapi.d.ts +4 -0
- package/dist/openapi.js +54 -0
- package/dist/routes/agents.d.ts +12 -0
- package/dist/routes/agents.js +147 -0
- package/dist/routes/chat.d.ts +13 -0
- package/dist/routes/chat.js +305 -0
- package/dist/routes/chatDataStream.d.ts +13 -0
- package/dist/routes/chatDataStream.js +365 -0
- package/dist/routes/mcp.d.ts +13 -0
- package/dist/routes/mcp.js +495 -0
- package/dist/services/AgentSession.d.ts +356 -0
- package/dist/services/AgentSession.js +1208 -0
- package/dist/services/ArtifactParser.d.ts +105 -0
- package/dist/services/ArtifactParser.js +338 -0
- package/dist/services/ArtifactService.d.ts +123 -0
- package/dist/services/ArtifactService.js +612 -0
- package/dist/services/BaseCompressor.d.ts +183 -0
- package/dist/services/BaseCompressor.js +500 -0
- package/dist/services/ConversationCompressor.d.ts +32 -0
- package/dist/services/ConversationCompressor.js +91 -0
- package/dist/services/IncrementalStreamParser.d.ts +98 -0
- package/dist/services/IncrementalStreamParser.js +327 -0
- package/dist/services/MidGenerationCompressor.d.ts +63 -0
- package/dist/services/MidGenerationCompressor.js +104 -0
- package/dist/services/PendingToolApprovalManager.d.ts +62 -0
- package/dist/services/PendingToolApprovalManager.js +133 -0
- package/dist/services/ResponseFormatter.d.ts +39 -0
- package/dist/services/ResponseFormatter.js +152 -0
- package/dist/tools/NativeSandboxExecutor.d.ts +38 -0
- package/dist/tools/NativeSandboxExecutor.js +432 -0
- package/dist/tools/SandboxExecutorFactory.d.ts +36 -0
- package/dist/tools/SandboxExecutorFactory.js +80 -0
- package/dist/tools/VercelSandboxExecutor.d.ts +71 -0
- package/dist/tools/VercelSandboxExecutor.js +340 -0
- package/dist/tools/distill-conversation-history-tool.d.ts +62 -0
- package/dist/tools/distill-conversation-history-tool.js +206 -0
- package/dist/tools/distill-conversation-tool.d.ts +41 -0
- package/dist/tools/distill-conversation-tool.js +141 -0
- package/dist/tools/sandbox-utils.d.ts +18 -0
- package/dist/tools/sandbox-utils.js +53 -0
- package/dist/types/chat.d.ts +27 -0
- package/dist/types/chat.js +1 -0
- package/dist/types/execution-context.d.ts +46 -0
- package/dist/types/execution-context.js +27 -0
- package/dist/types/xml.d.ts +5 -0
- package/dist/utils/SchemaProcessor.d.ts +52 -0
- package/dist/utils/SchemaProcessor.js +182 -0
- package/dist/utils/agent-operations.d.ts +62 -0
- package/dist/utils/agent-operations.js +53 -0
- package/dist/utils/artifact-component-schema.d.ts +42 -0
- package/dist/utils/artifact-component-schema.js +186 -0
- package/dist/utils/cleanup.d.ts +21 -0
- package/dist/utils/cleanup.js +59 -0
- package/dist/utils/data-component-schema.d.ts +2 -0
- package/dist/utils/data-component-schema.js +3 -0
- package/dist/utils/default-status-schemas.d.ts +20 -0
- package/dist/utils/default-status-schemas.js +24 -0
- package/dist/utils/json-postprocessor.d.ts +13 -0
- package/dist/{json-postprocessor.cjs → utils/json-postprocessor.js} +2 -3
- package/dist/utils/model-context-utils.d.ts +39 -0
- package/dist/utils/model-context-utils.js +181 -0
- package/dist/utils/model-resolver.d.ts +6 -0
- package/dist/utils/model-resolver.js +34 -0
- package/dist/utils/schema-validation.d.ts +44 -0
- package/dist/utils/schema-validation.js +97 -0
- package/dist/utils/stream-helpers.d.ts +197 -0
- package/dist/utils/stream-helpers.js +518 -0
- package/dist/utils/stream-registry.d.ts +22 -0
- package/dist/utils/stream-registry.js +34 -0
- package/dist/utils/token-estimator.d.ts +69 -0
- package/dist/utils/token-estimator.js +53 -0
- package/dist/utils/tracer.d.ts +7 -0
- package/dist/utils/tracer.js +7 -0
- package/package.json +10 -26
- package/dist/SandboxExecutorFactory.cjs +0 -895
- package/dist/SandboxExecutorFactory.js +0 -893
- package/dist/SandboxExecutorFactory.js.map +0 -1
- package/dist/chunk-VBDAOXYI.cjs +0 -927
- package/dist/chunk-VBDAOXYI.js +0 -832
- package/dist/chunk-VBDAOXYI.js.map +0 -1
- package/dist/chunk.cjs +0 -34
- package/dist/conversations.cjs +0 -7
- package/dist/conversations.js +0 -7
- package/dist/conversations2.cjs +0 -209
- package/dist/conversations2.js +0 -180
- package/dist/conversations2.js.map +0 -1
- package/dist/dbClient.cjs +0 -9676
- package/dist/dbClient.js +0 -9670
- package/dist/dbClient.js.map +0 -1
- package/dist/dbClient2.cjs +0 -5
- package/dist/dbClient2.js +0 -5
- package/dist/env.cjs +0 -59
- package/dist/env.js.map +0 -1
- package/dist/execution-limits.cjs +0 -260
- package/dist/execution-limits.js +0 -63
- package/dist/execution-limits.js.map +0 -1
- package/dist/index.cjs +0 -11411
- package/dist/index.d.cts +0 -36
- package/dist/index.d.cts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/instrumentation.cjs +0 -12
- package/dist/instrumentation.d.cts +0 -18
- package/dist/instrumentation.d.cts.map +0 -1
- package/dist/instrumentation.d.ts.map +0 -1
- package/dist/instrumentation2.cjs +0 -116
- package/dist/instrumentation2.js +0 -69
- package/dist/instrumentation2.js.map +0 -1
- package/dist/json-postprocessor.js +0 -20
- package/dist/json-postprocessor.js.map +0 -1
- package/dist/logger.cjs +0 -5
- package/dist/logger2.cjs +0 -1
- package/dist/nodefs.cjs +0 -29
- package/dist/nodefs.js +0 -27
- package/dist/nodefs.js.map +0 -1
- package/dist/opfs-ahp.cjs +0 -367
- package/dist/opfs-ahp.js +0 -368
- 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 };
|