@inkeep/agents-run-api 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/README.md +117 -0
  2. package/dist/AgentExecutionServer.d.ts +23 -0
  3. package/dist/AgentExecutionServer.d.ts.map +1 -0
  4. package/dist/AgentExecutionServer.js +32 -0
  5. package/dist/__tests__/setup.d.ts +4 -0
  6. package/dist/__tests__/setup.d.ts.map +1 -0
  7. package/dist/__tests__/setup.js +50 -0
  8. package/dist/__tests__/utils/testProject.d.ts +18 -0
  9. package/dist/__tests__/utils/testProject.d.ts.map +1 -0
  10. package/dist/__tests__/utils/testProject.js +26 -0
  11. package/dist/__tests__/utils/testRequest.d.ts +8 -0
  12. package/dist/__tests__/utils/testRequest.d.ts.map +1 -0
  13. package/dist/__tests__/utils/testRequest.js +32 -0
  14. package/dist/__tests__/utils/testTenant.d.ts +64 -0
  15. package/dist/__tests__/utils/testTenant.d.ts.map +1 -0
  16. package/dist/__tests__/utils/testTenant.js +71 -0
  17. package/dist/a2a/client.d.ts +182 -0
  18. package/dist/a2a/client.d.ts.map +1 -0
  19. package/dist/a2a/client.js +645 -0
  20. package/dist/a2a/handlers.d.ts +4 -0
  21. package/dist/a2a/handlers.d.ts.map +1 -0
  22. package/dist/a2a/handlers.js +657 -0
  23. package/dist/a2a/transfer.d.ts +18 -0
  24. package/dist/a2a/transfer.d.ts.map +1 -0
  25. package/dist/a2a/transfer.js +22 -0
  26. package/dist/a2a/types.d.ts +63 -0
  27. package/dist/a2a/types.d.ts.map +1 -0
  28. package/dist/a2a/types.js +1 -0
  29. package/dist/agents/Agent.d.ts +154 -0
  30. package/dist/agents/Agent.d.ts.map +1 -0
  31. package/dist/agents/Agent.js +1105 -0
  32. package/dist/agents/ModelFactory.d.ts +62 -0
  33. package/dist/agents/ModelFactory.d.ts.map +1 -0
  34. package/dist/agents/ModelFactory.js +208 -0
  35. package/dist/agents/SystemPromptBuilder.d.ts +14 -0
  36. package/dist/agents/SystemPromptBuilder.d.ts.map +1 -0
  37. package/dist/agents/SystemPromptBuilder.js +62 -0
  38. package/dist/agents/ToolSessionManager.d.ts +61 -0
  39. package/dist/agents/ToolSessionManager.d.ts.map +1 -0
  40. package/dist/agents/ToolSessionManager.js +143 -0
  41. package/dist/agents/artifactTools.d.ts +30 -0
  42. package/dist/agents/artifactTools.d.ts.map +1 -0
  43. package/dist/agents/artifactTools.js +463 -0
  44. package/dist/agents/generateTaskHandler.d.ts +41 -0
  45. package/dist/agents/generateTaskHandler.d.ts.map +1 -0
  46. package/dist/agents/generateTaskHandler.js +350 -0
  47. package/dist/agents/relationTools.d.ts +33 -0
  48. package/dist/agents/relationTools.d.ts.map +1 -0
  49. package/dist/agents/relationTools.js +245 -0
  50. package/dist/agents/types.d.ts +23 -0
  51. package/dist/agents/types.d.ts.map +1 -0
  52. package/dist/agents/types.js +1 -0
  53. package/dist/agents/versions/V1Config.d.ts +21 -0
  54. package/dist/agents/versions/V1Config.d.ts.map +1 -0
  55. package/dist/agents/versions/V1Config.js +285 -0
  56. package/dist/app.d.ts +4 -0
  57. package/dist/app.d.ts.map +1 -0
  58. package/dist/app.js +194 -0
  59. package/dist/data/agentGraph.d.ts +4 -0
  60. package/dist/data/agentGraph.d.ts.map +1 -0
  61. package/dist/data/agentGraph.js +73 -0
  62. package/dist/data/agents.d.ts +4 -0
  63. package/dist/data/agents.d.ts.map +1 -0
  64. package/dist/data/agents.js +73 -0
  65. package/dist/data/conversations.d.ts +59 -0
  66. package/dist/data/conversations.d.ts.map +1 -0
  67. package/dist/data/conversations.js +216 -0
  68. package/dist/data/db/clean.d.ts +6 -0
  69. package/dist/data/db/clean.d.ts.map +1 -0
  70. package/dist/data/db/clean.js +77 -0
  71. package/dist/data/db/dbClient.d.ts +3 -0
  72. package/dist/data/db/dbClient.d.ts.map +1 -0
  73. package/dist/data/db/dbClient.js +13 -0
  74. package/dist/env.d.ts +43 -0
  75. package/dist/env.d.ts.map +1 -0
  76. package/dist/env.js +63 -0
  77. package/dist/handlers/executionHandler.d.ts +36 -0
  78. package/dist/handlers/executionHandler.d.ts.map +1 -0
  79. package/dist/handlers/executionHandler.js +402 -0
  80. package/dist/index.d.ts +5 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js +43 -0
  83. package/dist/instrumentation.d.ts +13 -0
  84. package/dist/instrumentation.d.ts.map +1 -0
  85. package/dist/instrumentation.js +66 -0
  86. package/dist/logger.d.ts +4 -0
  87. package/dist/logger.d.ts.map +1 -0
  88. package/dist/logger.js +32 -0
  89. package/dist/middleware/api-key-auth.d.ts +22 -0
  90. package/dist/middleware/api-key-auth.d.ts.map +1 -0
  91. package/dist/middleware/api-key-auth.js +139 -0
  92. package/dist/middleware/index.d.ts +2 -0
  93. package/dist/middleware/index.d.ts.map +1 -0
  94. package/dist/middleware/index.js +1 -0
  95. package/dist/openapi.d.ts +2 -0
  96. package/dist/openapi.d.ts.map +1 -0
  97. package/dist/openapi.js +36 -0
  98. package/dist/routes/agents.d.ts +4 -0
  99. package/dist/routes/agents.d.ts.map +1 -0
  100. package/dist/routes/agents.js +155 -0
  101. package/dist/routes/chat.d.ts +4 -0
  102. package/dist/routes/chat.d.ts.map +1 -0
  103. package/dist/routes/chat.js +308 -0
  104. package/dist/routes/chatDataStream.d.ts +4 -0
  105. package/dist/routes/chatDataStream.d.ts.map +1 -0
  106. package/dist/routes/chatDataStream.js +179 -0
  107. package/dist/routes/mcp.d.ts +4 -0
  108. package/dist/routes/mcp.d.ts.map +1 -0
  109. package/dist/routes/mcp.js +500 -0
  110. package/dist/tracer.d.ts +24 -0
  111. package/dist/tracer.d.ts.map +1 -0
  112. package/dist/tracer.js +97 -0
  113. package/dist/types/chat.d.ts +25 -0
  114. package/dist/types/chat.d.ts.map +1 -0
  115. package/dist/types/chat.js +1 -0
  116. package/dist/types/execution-context.d.ts +14 -0
  117. package/dist/types/execution-context.d.ts.map +1 -0
  118. package/dist/types/execution-context.js +14 -0
  119. package/dist/utils/agent-operations.d.ts +79 -0
  120. package/dist/utils/agent-operations.d.ts.map +1 -0
  121. package/dist/utils/agent-operations.js +67 -0
  122. package/dist/utils/artifact-component-schema.d.ts +29 -0
  123. package/dist/utils/artifact-component-schema.d.ts.map +1 -0
  124. package/dist/utils/artifact-component-schema.js +119 -0
  125. package/dist/utils/artifact-parser.d.ts +71 -0
  126. package/dist/utils/artifact-parser.d.ts.map +1 -0
  127. package/dist/utils/artifact-parser.js +251 -0
  128. package/dist/utils/cleanup.d.ts +19 -0
  129. package/dist/utils/cleanup.d.ts.map +1 -0
  130. package/dist/utils/cleanup.js +66 -0
  131. package/dist/utils/data-component-schema.d.ts +6 -0
  132. package/dist/utils/data-component-schema.d.ts.map +1 -0
  133. package/dist/utils/data-component-schema.js +43 -0
  134. package/dist/utils/graph-session.d.ts +200 -0
  135. package/dist/utils/graph-session.d.ts.map +1 -0
  136. package/dist/utils/graph-session.js +1009 -0
  137. package/dist/utils/incremental-stream-parser.d.ts +57 -0
  138. package/dist/utils/incremental-stream-parser.d.ts.map +1 -0
  139. package/dist/utils/incremental-stream-parser.js +287 -0
  140. package/dist/utils/response-formatter.d.ts +27 -0
  141. package/dist/utils/response-formatter.d.ts.map +1 -0
  142. package/dist/utils/response-formatter.js +160 -0
  143. package/dist/utils/stream-helpers.d.ts +162 -0
  144. package/dist/utils/stream-helpers.d.ts.map +1 -0
  145. package/dist/utils/stream-helpers.js +385 -0
  146. package/dist/utils/stream-registry.d.ts +18 -0
  147. package/dist/utils/stream-registry.d.ts.map +1 -0
  148. package/dist/utils/stream-registry.js +33 -0
  149. package/package.json +88 -0
@@ -0,0 +1,57 @@
1
+ import { type StreamPart } from './artifact-parser.js';
2
+ import type { StreamHelper } from './stream-helpers.js';
3
+ /**
4
+ * Incremental parser that processes streaming text and formats artifacts/objects as they become complete
5
+ * Uses the unified ArtifactParser to eliminate redundancy
6
+ */
7
+ export declare class IncrementalStreamParser {
8
+ private buffer;
9
+ private pendingTextBuffer;
10
+ private streamHelper;
11
+ private artifactParser;
12
+ private contextId;
13
+ private hasStartedRole;
14
+ private collectedParts;
15
+ constructor(streamHelper: StreamHelper, tenantId: string, contextId: string);
16
+ /**
17
+ * Process a new text chunk for text streaming (handles artifact markers)
18
+ */
19
+ processTextChunk(chunk: string): Promise<void>;
20
+ /**
21
+ * Process a new object chunk for object streaming (handles JSON objects with artifact references)
22
+ */
23
+ processObjectChunk(chunk: string): Promise<void>;
24
+ /**
25
+ * Process tool call stream for structured output, streaming components as they complete
26
+ */
27
+ processToolCallStream(stream: AsyncIterable<any>, targetToolName: string): Promise<void>;
28
+ /**
29
+ * Legacy method for backward compatibility - defaults to text processing
30
+ */
31
+ processChunk(chunk: string): Promise<void>;
32
+ /**
33
+ * Process any remaining buffer content at the end of stream
34
+ */
35
+ finalize(): Promise<void>;
36
+ /**
37
+ * Get all collected parts for building the final response
38
+ */
39
+ getCollectedParts(): StreamPart[];
40
+ /**
41
+ * Parse buffer for complete artifacts and text parts (for text streaming)
42
+ */
43
+ private parseTextBuffer;
44
+ /**
45
+ * Parse buffer for complete JSON objects with artifact references (for object streaming)
46
+ */
47
+ private parseObjectBuffer;
48
+ /**
49
+ * Check if text might be the start of an artifact marker
50
+ */
51
+ private mightBeArtifactStart;
52
+ /**
53
+ * Stream a formatted part (text or data) with smart buffering
54
+ */
55
+ private streamPart;
56
+ }
57
+ //# sourceMappingURL=incremental-stream-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"incremental-stream-parser.d.ts","sourceRoot":"","sources":["../../src/utils/incremental-stream-parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AASxD;;;GAGG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,cAAc,CAAoB;gBAE9B,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAM3E;;OAEG;IACG,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcpD;;OAEG;IACG,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IActD;;OAEG;IACG,qBAAqB,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsE9F;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAgC/B;;OAEG;IACH,iBAAiB,IAAI,UAAU,EAAE;IAIjC;;OAEG;YACW,eAAe;IAoD7B;;OAEG;YACW,iBAAiB;IA4B/B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAK5B;;OAEG;YACW,UAAU;CAqDzB"}
@@ -0,0 +1,287 @@
1
+ import { getLogger } from '../logger.js';
2
+ import { ArtifactParser } from './artifact-parser.js';
3
+ const logger = getLogger('IncrementalStreamParser');
4
+ /**
5
+ * Incremental parser that processes streaming text and formats artifacts/objects as they become complete
6
+ * Uses the unified ArtifactParser to eliminate redundancy
7
+ */
8
+ export class IncrementalStreamParser {
9
+ buffer = '';
10
+ pendingTextBuffer = '';
11
+ streamHelper;
12
+ artifactParser;
13
+ contextId;
14
+ hasStartedRole = false;
15
+ collectedParts = [];
16
+ constructor(streamHelper, tenantId, contextId) {
17
+ this.streamHelper = streamHelper;
18
+ this.contextId = contextId;
19
+ this.artifactParser = new ArtifactParser(tenantId);
20
+ }
21
+ /**
22
+ * Process a new text chunk for text streaming (handles artifact markers)
23
+ */
24
+ async processTextChunk(chunk) {
25
+ this.buffer += chunk;
26
+ const parseResult = await this.parseTextBuffer();
27
+ // Stream complete parts
28
+ for (const part of parseResult.completeParts) {
29
+ await this.streamPart(part);
30
+ }
31
+ // Update buffer with remaining content
32
+ this.buffer = parseResult.remainingBuffer;
33
+ }
34
+ /**
35
+ * Process a new object chunk for object streaming (handles JSON objects with artifact references)
36
+ */
37
+ async processObjectChunk(chunk) {
38
+ this.buffer += chunk;
39
+ const parseResult = await this.parseObjectBuffer();
40
+ // Stream complete parts
41
+ for (const part of parseResult.completeParts) {
42
+ await this.streamPart(part);
43
+ }
44
+ // Update buffer with remaining content
45
+ this.buffer = parseResult.remainingBuffer;
46
+ }
47
+ /**
48
+ * Process tool call stream for structured output, streaming components as they complete
49
+ */
50
+ async processToolCallStream(stream, targetToolName) {
51
+ let jsonBuffer = '';
52
+ let componentBuffer = '';
53
+ let depth = 0;
54
+ let inDataComponents = false;
55
+ let componentsStreamed = 0;
56
+ for await (const part of stream) {
57
+ // Look for tool call deltas with incremental JSON
58
+ if (part.type === 'tool-call-delta' && part.toolName === targetToolName) {
59
+ const delta = part.argsTextDelta || '';
60
+ jsonBuffer += delta;
61
+ // Parse character by character to detect complete components
62
+ for (const char of delta) {
63
+ componentBuffer += char;
64
+ // Track JSON depth
65
+ if (char === '{') {
66
+ depth++;
67
+ }
68
+ else if (char === '}') {
69
+ depth--;
70
+ // At depth 2, we're inside the dataComponents array
71
+ // When we return to depth 2, we have a complete component
72
+ if (depth === 2 && componentBuffer.includes('"id"')) {
73
+ // Extract just the component object
74
+ const componentMatch = componentBuffer.match(/\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/);
75
+ if (componentMatch) {
76
+ try {
77
+ const component = JSON.parse(componentMatch[0]);
78
+ // Stream this individual component
79
+ const parts = await this.artifactParser.parseObject({ dataComponents: [component] });
80
+ for (const part of parts) {
81
+ await this.streamPart(part);
82
+ }
83
+ componentsStreamed++;
84
+ componentBuffer = ''; // Reset for next component
85
+ }
86
+ catch (e) {
87
+ // Not valid JSON yet, keep accumulating
88
+ logger.debug({ error: e }, 'Failed to parse component, continuing to accumulate');
89
+ }
90
+ }
91
+ }
92
+ }
93
+ // Detect when we enter dataComponents array
94
+ if (componentBuffer.includes('"dataComponents"') && componentBuffer.includes('[')) {
95
+ inDataComponents = true;
96
+ }
97
+ }
98
+ }
99
+ // Alternative: if the SDK provides complete tool calls (not deltas)
100
+ else if (part.type === 'tool-call' && part.toolName === targetToolName) {
101
+ // Process the complete args at once
102
+ if (part.args?.dataComponents) {
103
+ const parts = await this.artifactParser.parseObject(part.args);
104
+ for (const part of parts) {
105
+ await this.streamPart(part);
106
+ }
107
+ }
108
+ break; // Tool call complete
109
+ }
110
+ }
111
+ logger.debug({ componentsStreamed }, 'Finished streaming components');
112
+ }
113
+ /**
114
+ * Legacy method for backward compatibility - defaults to text processing
115
+ */
116
+ async processChunk(chunk) {
117
+ await this.processTextChunk(chunk);
118
+ }
119
+ /**
120
+ * Process any remaining buffer content at the end of stream
121
+ */
122
+ async finalize() {
123
+ if (this.buffer.trim()) {
124
+ // Process remaining buffer as final text
125
+ const part = {
126
+ kind: 'text',
127
+ text: this.buffer.trim(),
128
+ };
129
+ await this.streamPart(part);
130
+ }
131
+ // Flush any remaining buffered text
132
+ if (this.pendingTextBuffer.trim()) {
133
+ // Clean up any artifact-related tags or remnants before final flush
134
+ const cleanedText = this.pendingTextBuffer
135
+ .replace(/<\/?artifact:ref[^>]*>/g, '') // Remove all artifact:ref tags (opening and closing)
136
+ .replace(/<\/?artifact[^>]*>/g, '') // Remove all artifact tags
137
+ .replace(/<\/[^>]*artifact[^>]*>/g, '') // Remove closing tags with artifact in the name
138
+ .replace(/<[^>]*artifact[^>]*\/?>/g, '') // Remove any remaining artifact-related tags
139
+ .trim();
140
+ if (cleanedText) {
141
+ this.collectedParts.push({
142
+ kind: 'text',
143
+ text: cleanedText,
144
+ });
145
+ await this.streamHelper.streamText(cleanedText, 50);
146
+ }
147
+ this.pendingTextBuffer = '';
148
+ }
149
+ }
150
+ /**
151
+ * Get all collected parts for building the final response
152
+ */
153
+ getCollectedParts() {
154
+ return [...this.collectedParts];
155
+ }
156
+ /**
157
+ * Parse buffer for complete artifacts and text parts (for text streaming)
158
+ */
159
+ async parseTextBuffer() {
160
+ const completeParts = [];
161
+ const workingBuffer = this.buffer;
162
+ // Check if we have incomplete artifact markers
163
+ if (this.artifactParser.hasIncompleteArtifact(workingBuffer)) {
164
+ // Find safe boundary to stream text before incomplete artifact
165
+ const safeEnd = this.artifactParser.findSafeTextBoundary(workingBuffer);
166
+ if (safeEnd > 0) {
167
+ const safeText = workingBuffer.slice(0, safeEnd);
168
+ // Parse the safe portion for complete artifacts
169
+ const parts = await this.artifactParser.parseText(safeText);
170
+ completeParts.push(...parts);
171
+ return {
172
+ completeParts,
173
+ remainingBuffer: workingBuffer.slice(safeEnd),
174
+ };
175
+ }
176
+ // Buffer contains only incomplete artifact
177
+ return {
178
+ completeParts: [],
179
+ remainingBuffer: workingBuffer,
180
+ };
181
+ }
182
+ // No incomplete artifacts, parse the entire buffer
183
+ const parts = await this.artifactParser.parseText(workingBuffer);
184
+ // Check last part - if it's text, it might be incomplete
185
+ if (parts.length > 0 && parts[parts.length - 1].kind === 'text') {
186
+ const lastPart = parts[parts.length - 1];
187
+ const lastText = lastPart.text || '';
188
+ // Keep some text in buffer if it might be start of artifact
189
+ if (this.mightBeArtifactStart(lastText)) {
190
+ parts.pop(); // Remove last text part
191
+ return {
192
+ completeParts: parts,
193
+ remainingBuffer: lastText,
194
+ };
195
+ }
196
+ }
197
+ return {
198
+ completeParts: parts,
199
+ remainingBuffer: '',
200
+ };
201
+ }
202
+ /**
203
+ * Parse buffer for complete JSON objects with artifact references (for object streaming)
204
+ */
205
+ async parseObjectBuffer() {
206
+ const completeParts = [];
207
+ try {
208
+ // Try to parse as complete JSON
209
+ const parsed = JSON.parse(this.buffer);
210
+ const parts = await this.artifactParser.parseObject(parsed);
211
+ return {
212
+ completeParts: parts,
213
+ remainingBuffer: '',
214
+ };
215
+ }
216
+ catch {
217
+ // JSON is incomplete, try partial parsing
218
+ const { complete, remaining } = this.artifactParser.parsePartialJSON(this.buffer);
219
+ for (const obj of complete) {
220
+ const parts = await this.artifactParser.parseObject(obj);
221
+ completeParts.push(...parts);
222
+ }
223
+ return {
224
+ completeParts,
225
+ remainingBuffer: remaining,
226
+ };
227
+ }
228
+ }
229
+ /**
230
+ * Check if text might be the start of an artifact marker
231
+ */
232
+ mightBeArtifactStart(text) {
233
+ const lastChars = text.slice(-20); // Check last 20 chars
234
+ return lastChars.includes('<') && !lastChars.includes('/>');
235
+ }
236
+ /**
237
+ * Stream a formatted part (text or data) with smart buffering
238
+ */
239
+ async streamPart(part) {
240
+ // Collect for final response
241
+ this.collectedParts.push({ ...part });
242
+ if (!this.hasStartedRole) {
243
+ await this.streamHelper.writeRole('assistant');
244
+ this.hasStartedRole = true;
245
+ }
246
+ if (part.kind === 'text' && part.text) {
247
+ // Add to pending buffer
248
+ this.pendingTextBuffer += part.text;
249
+ // Flush if safe to do so
250
+ if (!this.artifactParser.hasIncompleteArtifact(this.pendingTextBuffer)) {
251
+ // Clean up any artifact-related tags or remnants before flushing
252
+ const cleanedText = this.pendingTextBuffer
253
+ .replace(/<\/?artifact:ref[^>]*>/g, '') // Remove all artifact:ref tags (opening and closing)
254
+ .replace(/<\/?artifact[^>]*>/g, '') // Remove all artifact tags
255
+ .replace(/<\/[^>]*artifact[^>]*>/g, '') // Remove closing tags with artifact in the name
256
+ .replace(/<[^>]*artifact[^>]*\/?>/g, ''); // Remove any remaining artifact-related tags
257
+ if (cleanedText.trim()) {
258
+ await this.streamHelper.streamText(cleanedText, 50);
259
+ }
260
+ this.pendingTextBuffer = '';
261
+ }
262
+ }
263
+ else if (part.kind === 'data' && part.data) {
264
+ // Flush any pending text before streaming data
265
+ if (this.pendingTextBuffer) {
266
+ // Clean up any artifact-related tags or remnants before flushing
267
+ const cleanedText = this.pendingTextBuffer
268
+ .replace(/<\/?artifact:ref[^>]*>/g, '') // Remove all artifact:ref tags (opening and closing)
269
+ .replace(/<\/?artifact[^>]*>/g, '') // Remove all artifact tags
270
+ .replace(/<\/[^>]*artifact[^>]*>/g, '') // Remove closing tags with artifact in the name
271
+ .replace(/<[^>]*artifact[^>]*\/?>/g, ''); // Remove any remaining artifact-related tags
272
+ if (cleanedText.trim()) {
273
+ await this.streamHelper.streamText(cleanedText, 50);
274
+ }
275
+ this.pendingTextBuffer = '';
276
+ }
277
+ // Determine if this is an artifact or regular data component
278
+ const isArtifact = part.data.artifactId && part.data.taskId;
279
+ if (isArtifact) {
280
+ await this.streamHelper.writeData('data-artifact', part.data);
281
+ }
282
+ else {
283
+ await this.streamHelper.writeData('data-component', part.data);
284
+ }
285
+ }
286
+ }
287
+ }
@@ -0,0 +1,27 @@
1
+ import type { MessageContent } from '@inkeep/agents-core';
2
+ /**
3
+ * Response formatter that uses the unified ArtifactParser to convert artifact markers
4
+ * into data parts for consistent artifact handling across all agent responses
5
+ */
6
+ export declare class ResponseFormatter {
7
+ private tenantId;
8
+ private artifactParser;
9
+ constructor(tenantId: string);
10
+ /**
11
+ * Process structured object response and replace artifact markers with actual artifacts
12
+ */
13
+ formatObjectResponse(responseObject: any, contextId: string): Promise<MessageContent>;
14
+ /**
15
+ * Process agent response and convert artifact markers to data parts
16
+ */
17
+ formatResponse(responseText: string, contextId: string): Promise<MessageContent>;
18
+ /**
19
+ * Count unique artifacts in parts array
20
+ */
21
+ private countUniqueArtifacts;
22
+ /**
23
+ * Log artifacts found in parts to span
24
+ */
25
+ private logArtifacts;
26
+ }
27
+ //# sourceMappingURL=response-formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-formatter.d.ts","sourceRoot":"","sources":["../../src/utils/response-formatter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAe1D;;;GAGG;AACH,qBAAa,iBAAiB;IAGhB,OAAO,CAAC,QAAQ;IAF5B,OAAO,CAAC,cAAc,CAAiB;gBAEnB,QAAQ,EAAE,MAAM;IAIpC;;OAEG;IACG,oBAAoB,CAAC,cAAc,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA0C3F;;OAEG;IACG,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAgEtF;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAgB5B;;OAEG;IACH,OAAO,CAAC,YAAY;CAwBrB"}
@@ -0,0 +1,160 @@
1
+ import { trace } from '@opentelemetry/api';
2
+ import { getLogger } from '../logger.js';
3
+ import { SERVICE_VERSION } from '../tracer.js';
4
+ import { ArtifactParser } from './artifact-parser.js';
5
+ const logger = getLogger('ResponseFormatter');
6
+ // Service name for response formatter tracer
7
+ const RESPONSE_FORMATTER_SERVICE = 'responseFormatter';
8
+ function getResponseFormatterTracer() {
9
+ const tracerProvider = trace.getTracerProvider();
10
+ return tracerProvider.getTracer(RESPONSE_FORMATTER_SERVICE, SERVICE_VERSION);
11
+ }
12
+ /**
13
+ * Response formatter that uses the unified ArtifactParser to convert artifact markers
14
+ * into data parts for consistent artifact handling across all agent responses
15
+ */
16
+ export class ResponseFormatter {
17
+ tenantId;
18
+ artifactParser;
19
+ constructor(tenantId) {
20
+ this.tenantId = tenantId;
21
+ this.artifactParser = new ArtifactParser(tenantId);
22
+ }
23
+ /**
24
+ * Process structured object response and replace artifact markers with actual artifacts
25
+ */
26
+ async formatObjectResponse(responseObject, contextId) {
27
+ const tracer = getResponseFormatterTracer();
28
+ return tracer.startActiveSpan('response.formatObject', async (span) => {
29
+ try {
30
+ // Get all artifacts available in this context
31
+ const artifactMap = await this.artifactParser.getContextArtifacts(contextId);
32
+ span.setAttributes({
33
+ 'response.type': 'object',
34
+ 'response.availableArtifacts': artifactMap.size,
35
+ });
36
+ // Parse the object using unified parser
37
+ const parts = await this.artifactParser.parseObject(responseObject, artifactMap);
38
+ // Count and log metrics
39
+ const uniqueArtifacts = this.countUniqueArtifacts(parts);
40
+ span.setAttributes({
41
+ 'response.dataPartsCount': parts.length,
42
+ 'response.artifactsCount': uniqueArtifacts,
43
+ 'response.totalPartsCount': parts.length,
44
+ });
45
+ this.logArtifacts(span, parts);
46
+ span.addEvent('response.parts.final_output', {
47
+ final_parts_array: JSON.stringify(parts, null, 2),
48
+ });
49
+ return { parts };
50
+ }
51
+ catch (error) {
52
+ span.recordException(error);
53
+ logger.error({ error, responseObject }, 'Error formatting object response');
54
+ return {
55
+ parts: [{ kind: 'data', data: responseObject }],
56
+ };
57
+ }
58
+ finally {
59
+ span.end();
60
+ }
61
+ });
62
+ }
63
+ /**
64
+ * Process agent response and convert artifact markers to data parts
65
+ */
66
+ async formatResponse(responseText, contextId) {
67
+ const tracer = getResponseFormatterTracer();
68
+ return tracer.startActiveSpan('response.format', async (span) => {
69
+ try {
70
+ span.setAttributes({
71
+ 'response.hasArtifactMarkers': this.artifactParser.hasArtifactMarkers(responseText),
72
+ 'response.contextId': contextId,
73
+ 'response.textLength': responseText.length,
74
+ });
75
+ // Check if the response contains artifact markers
76
+ if (!this.artifactParser.hasArtifactMarkers(responseText)) {
77
+ span.setAttributes({
78
+ 'response.result': 'no_markers_found',
79
+ });
80
+ return { parts: [{ kind: 'text', text: responseText }] };
81
+ }
82
+ // Get all artifacts available in this context
83
+ const artifactMap = await this.artifactParser.getContextArtifacts(contextId);
84
+ span.setAttributes({
85
+ 'response.type': 'text',
86
+ 'response.availableArtifacts': artifactMap.size,
87
+ });
88
+ // Parse text using unified parser
89
+ const parts = await this.artifactParser.parseText(responseText, artifactMap);
90
+ // If only one text part, return as plain text
91
+ if (parts.length === 1 && parts[0].kind === 'text') {
92
+ return { text: parts[0].text };
93
+ }
94
+ // Count and log metrics
95
+ const textParts = parts.filter((p) => p.kind === 'text').length;
96
+ const dataParts = parts.filter((p) => p.kind === 'data').length;
97
+ const uniqueArtifacts = this.countUniqueArtifacts(parts);
98
+ span.setAttributes({
99
+ 'response.textPartsCount': textParts,
100
+ 'response.dataPartsCount': dataParts,
101
+ 'response.artifactsCount': uniqueArtifacts,
102
+ 'response.totalPartsCount': parts.length,
103
+ });
104
+ this.logArtifacts(span, parts);
105
+ span.addEvent('response.parts.final_output', {
106
+ final_parts_array: JSON.stringify(parts, null, 2),
107
+ });
108
+ return { parts };
109
+ }
110
+ catch (error) {
111
+ span.recordException(error);
112
+ span.setStatus({ code: 2, message: error.message });
113
+ logger.error({ error, responseText }, 'Error formatting response');
114
+ return { text: responseText };
115
+ }
116
+ finally {
117
+ span.end();
118
+ }
119
+ });
120
+ }
121
+ /**
122
+ * Count unique artifacts in parts array
123
+ */
124
+ countUniqueArtifacts(parts) {
125
+ const uniqueKeys = new Set(parts
126
+ .filter((p) => p.kind === 'data')
127
+ .map((p) => {
128
+ const data = p.data;
129
+ if (data?.artifactId && data?.taskId) {
130
+ return `${data.artifactId}:${data.taskId}`;
131
+ }
132
+ return null;
133
+ })
134
+ .filter((key) => key !== null));
135
+ return uniqueKeys.size;
136
+ }
137
+ /**
138
+ * Log artifacts found in parts to span
139
+ */
140
+ logArtifacts(span, parts) {
141
+ const artifacts = parts
142
+ .filter((p) => p.kind === 'data')
143
+ .map((p) => {
144
+ const data = p.data;
145
+ return {
146
+ artifactId: data?.artifactId,
147
+ name: data?.name,
148
+ taskId: data?.taskId,
149
+ };
150
+ })
151
+ .filter((art) => art.artifactId && art.taskId);
152
+ if (artifacts.length > 0) {
153
+ const uniqueArtifactsList = Array.from(new Map(artifacts.map((art) => [`${art.artifactId}:${art.taskId}`, art])).values());
154
+ span.addEvent('artifacts.found', {
155
+ 'artifacts.count': uniqueArtifactsList.length,
156
+ 'artifacts.list': JSON.stringify(uniqueArtifactsList),
157
+ });
158
+ }
159
+ }
160
+ }