@vfarcic/dot-ai 0.124.0 → 0.126.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 (79) hide show
  1. package/assets/project-setup/templates/.github/CODEOWNERS.hbs +25 -0
  2. package/assets/project-setup/templates/.github/FUNDING.yml.hbs +35 -0
  3. package/assets/project-setup/templates/.github/ISSUE_TEMPLATE/bug_report.yml.hbs +175 -0
  4. package/assets/project-setup/templates/.github/ISSUE_TEMPLATE/config.yml.hbs +32 -0
  5. package/assets/project-setup/templates/.github/ISSUE_TEMPLATE/feature_request.yml.hbs +134 -0
  6. package/assets/project-setup/templates/.github/PULL_REQUEST_TEMPLATE.md.hbs +172 -0
  7. package/assets/project-setup/templates/.github/labeler.yml.hbs +123 -0
  8. package/assets/project-setup/templates/.github/release.yml.hbs +51 -0
  9. package/assets/project-setup/templates/.github/workflows/labeler.yml.hbs +21 -0
  10. package/assets/project-setup/templates/.github/workflows/scorecard.yml.hbs +71 -0
  11. package/assets/project-setup/templates/.github/workflows/stale.yml.hbs +57 -0
  12. package/dist/core/ai-provider-factory.d.ts.map +1 -1
  13. package/dist/core/ai-provider-factory.js +22 -5
  14. package/dist/core/ai-provider.interface.d.ts +16 -0
  15. package/dist/core/ai-provider.interface.d.ts.map +1 -1
  16. package/dist/core/capability-scan-workflow.d.ts +4 -9
  17. package/dist/core/capability-scan-workflow.d.ts.map +1 -1
  18. package/dist/core/capability-scan-workflow.js +203 -456
  19. package/dist/core/discovery.d.ts +6 -0
  20. package/dist/core/discovery.d.ts.map +1 -1
  21. package/dist/core/discovery.js +39 -3
  22. package/dist/core/embedding-service.d.ts +9 -36
  23. package/dist/core/embedding-service.d.ts.map +1 -1
  24. package/dist/core/embedding-service.js +137 -246
  25. package/dist/core/index.d.ts +1 -1
  26. package/dist/core/index.js +2 -2
  27. package/dist/core/kubernetes-utils.d.ts +1 -0
  28. package/dist/core/kubernetes-utils.d.ts.map +1 -1
  29. package/dist/core/kubernetes-utils.js +53 -48
  30. package/dist/core/model-config.d.ts +2 -0
  31. package/dist/core/model-config.d.ts.map +1 -1
  32. package/dist/core/model-config.js +3 -1
  33. package/dist/core/providers/anthropic-provider.d.ts.map +1 -1
  34. package/dist/core/providers/anthropic-provider.js +352 -282
  35. package/dist/core/providers/provider-debug-utils.d.ts +4 -0
  36. package/dist/core/providers/provider-debug-utils.d.ts.map +1 -1
  37. package/dist/core/providers/provider-debug-utils.js +25 -3
  38. package/dist/core/providers/vercel-provider.d.ts +1 -0
  39. package/dist/core/providers/vercel-provider.d.ts.map +1 -1
  40. package/dist/core/providers/vercel-provider.js +412 -345
  41. package/dist/core/tracing/ai-tracing.d.ts +80 -0
  42. package/dist/core/tracing/ai-tracing.d.ts.map +1 -0
  43. package/dist/core/tracing/ai-tracing.js +122 -0
  44. package/dist/core/tracing/config.d.ts +15 -0
  45. package/dist/core/tracing/config.d.ts.map +1 -0
  46. package/dist/core/tracing/config.js +133 -0
  47. package/dist/core/tracing/http-tracing.d.ts +28 -0
  48. package/dist/core/tracing/http-tracing.d.ts.map +1 -0
  49. package/dist/core/tracing/http-tracing.js +119 -0
  50. package/dist/core/tracing/index.d.ts +14 -0
  51. package/dist/core/tracing/index.d.ts.map +1 -0
  52. package/dist/core/tracing/index.js +40 -0
  53. package/dist/core/tracing/k8s-tracing.d.ts +57 -0
  54. package/dist/core/tracing/k8s-tracing.d.ts.map +1 -0
  55. package/dist/core/tracing/k8s-tracing.js +155 -0
  56. package/dist/core/tracing/qdrant-tracing.d.ts +68 -0
  57. package/dist/core/tracing/qdrant-tracing.d.ts.map +1 -0
  58. package/dist/core/tracing/qdrant-tracing.js +102 -0
  59. package/dist/core/tracing/tool-tracing.d.ts +31 -0
  60. package/dist/core/tracing/tool-tracing.d.ts.map +1 -0
  61. package/dist/core/tracing/tool-tracing.js +76 -0
  62. package/dist/core/tracing/tracer.d.ts +21 -0
  63. package/dist/core/tracing/tracer.d.ts.map +1 -0
  64. package/dist/core/tracing/tracer.js +215 -0
  65. package/dist/core/tracing/types.d.ts +86 -0
  66. package/dist/core/tracing/types.d.ts.map +1 -0
  67. package/dist/core/tracing/types.js +41 -0
  68. package/dist/core/unified-creation-session.js +1 -1
  69. package/dist/core/vector-db-service.d.ts.map +1 -1
  70. package/dist/core/vector-db-service.js +238 -163
  71. package/dist/interfaces/mcp.d.ts.map +1 -1
  72. package/dist/interfaces/mcp.js +71 -43
  73. package/dist/mcp/server.js +12 -2
  74. package/dist/tools/organizational-data.d.ts.map +1 -1
  75. package/dist/tools/organizational-data.js +2 -4
  76. package/dist/tools/version.d.ts +12 -1
  77. package/dist/tools/version.d.ts.map +1 -1
  78. package/dist/tools/version.js +24 -4
  79. package/package.json +11 -1
@@ -13,6 +13,8 @@ exports.AnthropicProvider = void 0;
13
13
  const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
14
14
  const provider_debug_utils_1 = require("./provider-debug-utils");
15
15
  const model_config_1 = require("../model-config");
16
+ const ai_tracing_1 = require("../tracing/ai-tracing");
17
+ const api_1 = require("@opentelemetry/api");
16
18
  class AnthropicProvider {
17
19
  client;
18
20
  apiKey;
@@ -21,14 +23,14 @@ class AnthropicProvider {
21
23
  constructor(config) {
22
24
  this.apiKey = config.apiKey;
23
25
  this.model = config.model || this.getDefaultModel();
24
- this.debugMode = config.debugMode ?? (process.env.DEBUG_DOT_AI === 'true');
26
+ this.debugMode = config.debugMode ?? process.env.DEBUG_DOT_AI === 'true';
25
27
  this.validateApiKey();
26
28
  this.client = new sdk_1.default({
27
29
  apiKey: this.apiKey,
28
30
  // Enable 1M token context window for Claude Sonnet 4 (5x increase from 200K)
29
31
  defaultHeaders: {
30
- 'anthropic-beta': 'context-1m-2025-08-07'
31
- }
32
+ 'anthropic-beta': 'context-1m-2025-08-07',
33
+ },
32
34
  });
33
35
  }
34
36
  validateApiKey() {
@@ -65,76 +67,87 @@ class AnthropicProvider {
65
67
  // Return the actual debug file names created
66
68
  return {
67
69
  promptFile: `${debugId}_prompt.md`,
68
- responseFile: `${debugId}_response.md`
70
+ responseFile: `${debugId}_response.md`,
69
71
  };
70
72
  }
71
73
  async sendMessage(message, operation = 'generic', evaluationContext) {
72
74
  if (!this.client) {
73
75
  throw new Error('Anthropic client not initialized');
74
76
  }
75
- const startTime = Date.now();
76
- try {
77
- // Make real API call to Anthropic with streaming
78
- const stream = await this.client.messages.create({
79
- model: this.model,
80
- max_tokens: 64000,
81
- messages: [{ role: 'user', content: message }],
82
- stream: true // Enable streaming by default to support long operations (>10 minutes)
83
- });
84
- let content = '';
85
- let input_tokens = 0;
86
- let output_tokens = 0;
87
- for await (const chunk of stream) {
88
- if (chunk.type === 'message_start') {
89
- input_tokens = chunk.message.usage.input_tokens;
90
- }
91
- else if (chunk.type === 'content_block_delta') {
92
- if (chunk.delta.type === 'text_delta') {
93
- content += chunk.delta.text;
77
+ return await (0, ai_tracing_1.withAITracing)({
78
+ provider: 'anthropic',
79
+ model: this.model,
80
+ operation: 'chat',
81
+ }, async () => {
82
+ const startTime = Date.now();
83
+ try {
84
+ // Make real API call to Anthropic with streaming
85
+ const stream = await this.client.messages.create({
86
+ model: this.model,
87
+ max_tokens: 64000,
88
+ messages: [{ role: 'user', content: message }],
89
+ stream: true, // Enable streaming by default to support long operations (>10 minutes)
90
+ });
91
+ let content = '';
92
+ let input_tokens = 0;
93
+ let output_tokens = 0;
94
+ for await (const chunk of stream) {
95
+ if (chunk.type === 'message_start') {
96
+ input_tokens = chunk.message.usage.input_tokens;
97
+ }
98
+ else if (chunk.type === 'content_block_delta') {
99
+ if (chunk.delta.type === 'text_delta') {
100
+ content += chunk.delta.text;
101
+ }
102
+ }
103
+ else if (chunk.type === 'message_delta') {
104
+ output_tokens = chunk.usage.output_tokens;
94
105
  }
95
106
  }
96
- else if (chunk.type === 'message_delta') {
97
- output_tokens = chunk.usage.output_tokens;
107
+ const response = {
108
+ content,
109
+ usage: {
110
+ input_tokens,
111
+ output_tokens,
112
+ },
113
+ };
114
+ // Debug log the interaction if enabled
115
+ this.logDebugIfEnabled(operation, message, response);
116
+ // PRD #154: Log evaluation dataset if evaluation context is provided
117
+ if (this.debugMode && evaluationContext?.interaction_id) {
118
+ const durationMs = Date.now() - startTime;
119
+ const evaluationMetrics = {
120
+ // Core execution data
121
+ operation,
122
+ sdk: this.getProviderType(),
123
+ inputTokens: input_tokens,
124
+ outputTokens: output_tokens,
125
+ durationMs,
126
+ // Required fields
127
+ iterationCount: 1,
128
+ toolCallCount: 0,
129
+ status: 'completed',
130
+ completionReason: 'stop',
131
+ modelVersion: this.model,
132
+ // Required evaluation context - NO DEFAULTS, must be provided
133
+ test_scenario: operation,
134
+ ai_response_summary: content,
135
+ user_intent: evaluationContext?.user_intent || '',
136
+ interaction_id: evaluationContext?.interaction_id || '',
137
+ };
138
+ (0, provider_debug_utils_1.logEvaluationDataset)(evaluationMetrics, this.debugMode);
98
139
  }
140
+ return response;
99
141
  }
100
- const response = {
101
- content,
102
- usage: {
103
- input_tokens,
104
- output_tokens
105
- }
106
- };
107
- // Debug log the interaction if enabled
108
- this.logDebugIfEnabled(operation, message, response);
109
- // PRD #154: Log evaluation dataset if evaluation context is provided
110
- if (this.debugMode && evaluationContext?.interaction_id) {
111
- const durationMs = Date.now() - startTime;
112
- const evaluationMetrics = {
113
- // Core execution data
114
- operation,
115
- sdk: this.getProviderType(),
116
- inputTokens: input_tokens,
117
- outputTokens: output_tokens,
118
- durationMs,
119
- // Required fields
120
- iterationCount: 1,
121
- toolCallCount: 0,
122
- status: 'completed',
123
- completionReason: 'stop',
124
- modelVersion: this.model,
125
- // Required evaluation context - NO DEFAULTS, must be provided
126
- test_scenario: operation,
127
- ai_response_summary: content,
128
- user_intent: evaluationContext?.user_intent || '',
129
- interaction_id: evaluationContext?.interaction_id || '',
130
- };
131
- (0, provider_debug_utils_1.logEvaluationDataset)(evaluationMetrics, this.debugMode);
142
+ catch (error) {
143
+ throw new Error(`Anthropic API error: ${error}`);
132
144
  }
133
- return response;
134
- }
135
- catch (error) {
136
- throw new Error(`Anthropic API error: ${error}`);
137
- }
145
+ }, (response) => ({
146
+ inputTokens: response.usage.input_tokens,
147
+ outputTokens: response.usage.output_tokens,
148
+ cacheReadTokens: response.usage.cache_read_input_tokens,
149
+ cacheCreationTokens: response.usage.cache_creation_input_tokens,
150
+ }));
138
151
  }
139
152
  /**
140
153
  * Agentic tool loop implementation
@@ -160,237 +173,294 @@ class AnthropicProvider {
160
173
  if (!this.client) {
161
174
  throw new Error('Anthropic client not initialized');
162
175
  }
163
- const startTime = Date.now();
164
- // Convert AITool[] to Anthropic Tool format with caching on last tool
165
- const tools = config.tools.map((t, index) => {
166
- const tool = {
167
- name: t.name,
168
- description: t.description,
169
- input_schema: t.inputSchema
176
+ return await (0, ai_tracing_1.withAITracing)({
177
+ provider: 'anthropic',
178
+ model: this.model,
179
+ operation: 'tool_loop',
180
+ }, async () => {
181
+ const startTime = Date.now();
182
+ // Convert AITool[] to Anthropic Tool format with caching on last tool
183
+ const tools = config.tools.map((t, index) => {
184
+ const tool = {
185
+ name: t.name,
186
+ description: t.description,
187
+ input_schema: t.inputSchema,
188
+ };
189
+ // Add cache control to the last tool to cache the entire tools array
190
+ if (index === config.tools.length - 1) {
191
+ tool.cache_control = { type: 'ephemeral' };
192
+ }
193
+ return tool;
194
+ });
195
+ // Separate system prompt with caching from user message
196
+ const systemPrompt = [
197
+ {
198
+ type: 'text',
199
+ text: config.systemPrompt,
200
+ cache_control: { type: 'ephemeral' },
201
+ },
202
+ ];
203
+ // Initialize conversation history with just the user message
204
+ const conversationHistory = [
205
+ {
206
+ role: 'user',
207
+ content: config.userMessage,
208
+ },
209
+ ];
210
+ let iterations = 0;
211
+ const toolCallsExecuted = [];
212
+ const totalTokens = {
213
+ input: 0,
214
+ output: 0,
215
+ cacheCreation: 0,
216
+ cacheRead: 0,
170
217
  };
171
- // Add cache control to the last tool to cache the entire tools array
172
- if (index === config.tools.length - 1) {
173
- tool.cache_control = { type: 'ephemeral' };
174
- }
175
- return tool;
176
- });
177
- // Separate system prompt with caching from user message
178
- const systemPrompt = [
179
- {
180
- type: 'text',
181
- text: config.systemPrompt,
182
- cache_control: { type: 'ephemeral' }
183
- }
184
- ];
185
- // Initialize conversation history with just the user message
186
- const conversationHistory = [
187
- {
188
- role: 'user',
189
- content: config.userMessage
190
- }
191
- ];
192
- let iterations = 0;
193
- const toolCallsExecuted = [];
194
- const totalTokens = { input: 0, output: 0, cacheCreation: 0, cacheRead: 0 };
195
- const maxIterations = config.maxIterations || 20;
196
- const operation = config.operation || 'tool-loop';
197
- try {
198
- while (iterations < maxIterations) {
199
- iterations++;
200
- // Build current prompt for debug logging
201
- const currentPrompt = `System: ${config.systemPrompt}\n\n${conversationHistory.map(msg => {
202
- let content = '';
203
- if (typeof msg.content === 'string') {
204
- content = msg.content;
205
- }
206
- else if (Array.isArray(msg.content)) {
207
- // Extract text from content blocks
208
- content = msg.content.map(block => {
209
- if (block.type === 'text') {
210
- return block.text;
218
+ const maxIterations = config.maxIterations || 20;
219
+ const operation = config.operation || 'tool-loop';
220
+ try {
221
+ const tracer = api_1.trace.getTracer('dot-ai-mcp');
222
+ while (iterations < maxIterations) {
223
+ iterations++;
224
+ // Wrap entire iteration in a span
225
+ // Returns result if investigation complete, null to continue
226
+ const iterationResult = await tracer.startActiveSpan('tool_loop_iteration', { kind: api_1.SpanKind.INTERNAL }, async (span) => {
227
+ try {
228
+ // Build current prompt for debug logging
229
+ const currentPrompt = `System: ${config.systemPrompt}\n\n${conversationHistory
230
+ .map(msg => {
231
+ let content = '';
232
+ if (typeof msg.content === 'string') {
233
+ content = msg.content;
234
+ }
235
+ else if (Array.isArray(msg.content)) {
236
+ // Extract text from content blocks
237
+ content = msg.content
238
+ .map(block => {
239
+ if (block.type === 'text') {
240
+ return block.text;
241
+ }
242
+ else if (block.type === 'tool_use') {
243
+ return `[TOOL_USE: ${block.name}]`;
244
+ }
245
+ else if (block.type === 'tool_result') {
246
+ const content = block.content;
247
+ if (typeof content === 'string') {
248
+ return `[TOOL_RESULT: ${block.tool_use_id}]\n${content}`;
249
+ }
250
+ else if (Array.isArray(content)) {
251
+ const textContent = content
252
+ .map(c => c.type === 'text' ? c.text : `[${c.type}]`)
253
+ .join(' ');
254
+ return `[TOOL_RESULT: ${block.tool_use_id}]\n${textContent}`;
255
+ }
256
+ return `[TOOL_RESULT: ${block.tool_use_id}]`;
257
+ }
258
+ return `[${block.type}]`;
259
+ })
260
+ .join(' ');
261
+ }
262
+ else {
263
+ content = '[complex_content]';
264
+ }
265
+ return `${msg.role}: ${content}`;
266
+ })
267
+ .join('\n\n')}`;
268
+ // Call Anthropic API with tools and cached system prompt
269
+ const response = await this.client.messages.create({
270
+ model: this.model,
271
+ max_tokens: 4096,
272
+ system: systemPrompt,
273
+ messages: conversationHistory,
274
+ tools: tools,
275
+ });
276
+ // Track token usage including cache metrics
277
+ totalTokens.input += response.usage.input_tokens;
278
+ totalTokens.output += response.usage.output_tokens;
279
+ // Track cache usage (available when prompt caching is used)
280
+ if ('cache_creation_input_tokens' in response.usage) {
281
+ totalTokens.cacheCreation +=
282
+ response.usage.cache_creation_input_tokens || 0;
283
+ }
284
+ if ('cache_read_input_tokens' in response.usage) {
285
+ totalTokens.cacheRead +=
286
+ response.usage.cache_read_input_tokens || 0;
287
+ }
288
+ // Check if AI wants to use tools
289
+ const toolUses = response.content.filter((c) => c.type === 'tool_use');
290
+ // Log debug for final iteration to capture complete prompts/responses for evaluation
291
+ let debugFiles = null;
292
+ if (toolUses.length === 0) {
293
+ const aiResponse = {
294
+ content: response.content
295
+ .filter((c) => c.type === 'text')
296
+ .map(c => c.text)
297
+ .join('\n\n'),
298
+ usage: {
299
+ input_tokens: response.usage.input_tokens,
300
+ output_tokens: response.usage.output_tokens,
301
+ cache_creation_input_tokens: response.usage
302
+ .cache_creation_input_tokens,
303
+ cache_read_input_tokens: response.usage
304
+ .cache_read_input_tokens,
305
+ },
306
+ };
307
+ debugFiles = this.logDebugIfEnabled(`${config.operation}-summary`, currentPrompt, aiResponse);
211
308
  }
212
- else if (block.type === 'tool_use') {
213
- return `[TOOL_USE: ${block.name}]`;
309
+ // If AI is done (no more tools to call), return the result
310
+ if (toolUses.length === 0) {
311
+ // AI is done - extract final text message
312
+ const textContent = response.content.find((c) => c.type === 'text');
313
+ // Return result from span callback
314
+ return (0, provider_debug_utils_1.createAndLogAgenticResult)({
315
+ finalMessage: textContent?.text || '',
316
+ iterations,
317
+ toolCallsExecuted,
318
+ totalTokens: {
319
+ input: totalTokens.input,
320
+ output: totalTokens.output,
321
+ cacheCreation: totalTokens.cacheCreation,
322
+ cacheRead: totalTokens.cacheRead,
323
+ },
324
+ status: 'success',
325
+ completionReason: 'investigation_complete',
326
+ modelVersion: this.model,
327
+ operation: `${operation}-summary`,
328
+ sdk: this.getProviderType(),
329
+ startTime,
330
+ debugMode: this.debugMode,
331
+ debugFiles,
332
+ evaluationContext: config.evaluationContext,
333
+ interaction_id: config.interaction_id,
334
+ });
214
335
  }
215
- else if (block.type === 'tool_result') {
216
- const content = block.content;
217
- if (typeof content === 'string') {
218
- return `[TOOL_RESULT: ${block.tool_use_id}]\n${content}`;
336
+ // Execute all requested tools in parallel
337
+ const toolResults = [];
338
+ // Create promises for parallel execution
339
+ const toolExecutionPromises = toolUses.map(async (toolUse) => {
340
+ try {
341
+ const result = await config.toolExecutor(toolUse.name, toolUse.input);
342
+ return {
343
+ success: true,
344
+ toolUse,
345
+ result,
346
+ };
219
347
  }
220
- else if (Array.isArray(content)) {
221
- const textContent = content.map(c => c.type === 'text' ? c.text : `[${c.type}]`).join(' ');
222
- return `[TOOL_RESULT: ${block.tool_use_id}]\n${textContent}`;
348
+ catch (error) {
349
+ return {
350
+ success: false,
351
+ toolUse,
352
+ error: error instanceof Error
353
+ ? error.message
354
+ : String(error),
355
+ };
356
+ }
357
+ });
358
+ // Execute all tools simultaneously
359
+ const executionResults = await Promise.all(toolExecutionPromises);
360
+ // Process results and build tool_result blocks
361
+ for (const executionResult of executionResults) {
362
+ if (executionResult.success) {
363
+ toolCallsExecuted.push({
364
+ tool: executionResult.toolUse.name,
365
+ input: executionResult.toolUse.input,
366
+ output: executionResult.result,
367
+ });
368
+ toolResults.push({
369
+ type: 'tool_result',
370
+ tool_use_id: executionResult.toolUse.id,
371
+ content: JSON.stringify(executionResult.result),
372
+ });
373
+ }
374
+ else {
375
+ // Feed error back to AI as tool result
376
+ toolResults.push({
377
+ type: 'tool_result',
378
+ tool_use_id: executionResult.toolUse.id,
379
+ content: JSON.stringify({
380
+ error: executionResult.error,
381
+ }),
382
+ is_error: true,
383
+ });
223
384
  }
224
- return `[TOOL_RESULT: ${block.tool_use_id}]`;
225
385
  }
226
- return `[${block.type}]`;
227
- }).join(' ');
228
- }
229
- else {
230
- content = '[complex_content]';
231
- }
232
- return `${msg.role}: ${content}`;
233
- }).join('\n\n')}`;
234
- // Call Anthropic API with tools and cached system prompt
235
- const response = await this.client.messages.create({
236
- model: this.model,
237
- max_tokens: 4096,
238
- system: systemPrompt,
239
- messages: conversationHistory,
240
- tools: tools
241
- });
242
- // Track token usage including cache metrics
243
- totalTokens.input += response.usage.input_tokens;
244
- totalTokens.output += response.usage.output_tokens;
245
- // Track cache usage (available when prompt caching is used)
246
- if ('cache_creation_input_tokens' in response.usage) {
247
- totalTokens.cacheCreation += response.usage.cache_creation_input_tokens || 0;
248
- }
249
- if ('cache_read_input_tokens' in response.usage) {
250
- totalTokens.cacheRead += response.usage.cache_read_input_tokens || 0;
251
- }
252
- // Check if AI wants to use tools
253
- const toolUses = response.content.filter((c) => c.type === 'tool_use');
254
- // Log debug for final iteration to capture complete prompts/responses for evaluation
255
- let debugFiles = null;
256
- if (toolUses.length === 0) {
257
- const aiResponse = {
258
- content: response.content
259
- .filter((c) => c.type === 'text')
260
- .map(c => c.text)
261
- .join('\n\n'),
262
- usage: {
263
- input_tokens: response.usage.input_tokens,
264
- output_tokens: response.usage.output_tokens,
265
- cache_creation_input_tokens: response.usage.cache_creation_input_tokens,
266
- cache_read_input_tokens: response.usage.cache_read_input_tokens
386
+ // Add AI response and tool results to conversation history
387
+ conversationHistory.push({ role: 'assistant', content: response.content }, { role: 'user', content: toolResults });
388
+ // Invoke iteration callback if provided
389
+ if (config.onIteration) {
390
+ config.onIteration(iterations, toolCallsExecuted);
391
+ }
392
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
393
+ // Return null to continue the loop
394
+ return null;
395
+ }
396
+ catch (error) {
397
+ span.recordException(error);
398
+ span.setStatus({
399
+ code: api_1.SpanStatusCode.ERROR,
400
+ message: error instanceof Error ? error.message : String(error),
401
+ });
402
+ throw error;
403
+ }
404
+ finally {
405
+ span.end();
267
406
  }
268
- };
269
- debugFiles = this.logDebugIfEnabled(`${config.operation}-summary`, currentPrompt, aiResponse);
270
- }
271
- if (toolUses.length === 0) {
272
- // AI is done - extract final text message
273
- const textContent = response.content.find((c) => c.type === 'text');
274
- return (0, provider_debug_utils_1.createAndLogAgenticResult)({
275
- finalMessage: textContent?.text || '',
276
- iterations,
277
- toolCallsExecuted,
278
- totalTokens: {
279
- input: totalTokens.input,
280
- output: totalTokens.output,
281
- cacheCreation: totalTokens.cacheCreation,
282
- cacheRead: totalTokens.cacheRead
283
- },
284
- status: 'success',
285
- completionReason: 'investigation_complete',
286
- modelVersion: this.model,
287
- operation: `${operation}-summary`,
288
- sdk: this.getProviderType(),
289
- startTime,
290
- debugMode: this.debugMode,
291
- debugFiles,
292
- evaluationContext: config.evaluationContext,
293
- interaction_id: config.interaction_id
294
407
  });
295
- }
296
- // Execute all requested tools in parallel
297
- const toolResults = [];
298
- // Create promises for parallel execution
299
- const toolExecutionPromises = toolUses.map(async (toolUse) => {
300
- try {
301
- const result = await config.toolExecutor(toolUse.name, toolUse.input);
302
- return {
303
- success: true,
304
- toolUse,
305
- result
306
- };
307
- }
308
- catch (error) {
309
- return {
310
- success: false,
311
- toolUse,
312
- error: error instanceof Error ? error.message : String(error)
313
- };
314
- }
315
- });
316
- // Execute all tools simultaneously
317
- const executionResults = await Promise.all(toolExecutionPromises);
318
- // Process results and build tool_result blocks
319
- for (const executionResult of executionResults) {
320
- if (executionResult.success) {
321
- toolCallsExecuted.push({
322
- tool: executionResult.toolUse.name,
323
- input: executionResult.toolUse.input,
324
- output: executionResult.result
325
- });
326
- toolResults.push({
327
- type: 'tool_result',
328
- tool_use_id: executionResult.toolUse.id,
329
- content: JSON.stringify(executionResult.result)
330
- });
331
- }
332
- else {
333
- // Feed error back to AI as tool result
334
- toolResults.push({
335
- type: 'tool_result',
336
- tool_use_id: executionResult.toolUse.id,
337
- content: JSON.stringify({ error: executionResult.error }),
338
- is_error: true
339
- });
408
+ // If iteration returned a result, investigation is complete
409
+ if (iterationResult) {
410
+ return iterationResult;
340
411
  }
341
412
  }
342
- // Add AI response and tool results to conversation history
343
- conversationHistory.push({ role: 'assistant', content: response.content }, { role: 'user', content: toolResults });
344
- // Invoke iteration callback if provided
345
- if (config.onIteration) {
346
- config.onIteration(iterations, toolCallsExecuted);
347
- }
413
+ // Reached max iterations without completion
414
+ return (0, provider_debug_utils_1.createAndLogAgenticResult)({
415
+ finalMessage: `Investigation incomplete - reached maximum ${maxIterations} iterations`,
416
+ iterations,
417
+ toolCallsExecuted,
418
+ totalTokens: {
419
+ input: totalTokens.input,
420
+ output: totalTokens.output,
421
+ cacheCreation: totalTokens.cacheCreation,
422
+ cacheRead: totalTokens.cacheRead,
423
+ },
424
+ status: 'failed',
425
+ completionReason: 'max_iterations',
426
+ modelVersion: this.model,
427
+ operation: `${operation}-max-iterations`,
428
+ sdk: this.getProviderType(),
429
+ startTime,
430
+ debugMode: this.debugMode,
431
+ evaluationContext: config.evaluationContext,
432
+ interaction_id: config.interaction_id,
433
+ });
348
434
  }
349
- // Reached max iterations without completion
350
- return (0, provider_debug_utils_1.createAndLogAgenticResult)({
351
- finalMessage: `Investigation incomplete - reached maximum ${maxIterations} iterations`,
352
- iterations,
353
- toolCallsExecuted,
354
- totalTokens: {
355
- input: totalTokens.input,
356
- output: totalTokens.output,
357
- cacheCreation: totalTokens.cacheCreation,
358
- cacheRead: totalTokens.cacheRead
359
- },
360
- status: 'failed',
361
- completionReason: 'max_iterations',
362
- modelVersion: this.model,
363
- operation: `${operation}-max-iterations`,
364
- sdk: this.getProviderType(),
365
- startTime,
366
- debugMode: this.debugMode,
367
- evaluationContext: config.evaluationContext,
368
- interaction_id: config.interaction_id
369
- });
370
- }
371
- catch (error) {
372
- // Return error result with extended metrics
373
- return (0, provider_debug_utils_1.createAndLogAgenticResult)({
374
- finalMessage: `Error during investigation: ${error instanceof Error ? error.message : String(error)}`,
375
- iterations,
376
- toolCallsExecuted,
377
- totalTokens: {
378
- input: totalTokens.input,
379
- output: totalTokens.output,
380
- cacheCreation: totalTokens.cacheCreation,
381
- cacheRead: totalTokens.cacheRead
382
- },
383
- status: 'failed',
384
- completionReason: 'error',
385
- modelVersion: this.model,
386
- operation: `${operation}-error`,
387
- sdk: this.getProviderType(),
388
- startTime,
389
- debugMode: this.debugMode,
390
- evaluationContext: config.evaluationContext,
391
- interaction_id: config.interaction_id
392
- });
393
- }
435
+ catch (error) {
436
+ // Return error result with extended metrics
437
+ return (0, provider_debug_utils_1.createAndLogAgenticResult)({
438
+ finalMessage: `Error during investigation: ${error instanceof Error ? error.message : String(error)}`,
439
+ iterations,
440
+ toolCallsExecuted,
441
+ totalTokens: {
442
+ input: totalTokens.input,
443
+ output: totalTokens.output,
444
+ cacheCreation: totalTokens.cacheCreation,
445
+ cacheRead: totalTokens.cacheRead,
446
+ },
447
+ status: 'failed',
448
+ completionReason: 'error',
449
+ modelVersion: this.model,
450
+ operation: `${operation}-error`,
451
+ sdk: this.getProviderType(),
452
+ startTime,
453
+ debugMode: this.debugMode,
454
+ evaluationContext: config.evaluationContext,
455
+ interaction_id: config.interaction_id,
456
+ });
457
+ }
458
+ }, (result) => ({
459
+ inputTokens: result.totalTokens.input,
460
+ outputTokens: result.totalTokens.output,
461
+ cacheReadTokens: result.totalTokens.cacheRead,
462
+ cacheCreationTokens: result.totalTokens.cacheCreation,
463
+ }));
394
464
  }
395
465
  }
396
466
  exports.AnthropicProvider = AnthropicProvider;