@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.
- package/assets/project-setup/templates/.github/CODEOWNERS.hbs +25 -0
- package/assets/project-setup/templates/.github/FUNDING.yml.hbs +35 -0
- package/assets/project-setup/templates/.github/ISSUE_TEMPLATE/bug_report.yml.hbs +175 -0
- package/assets/project-setup/templates/.github/ISSUE_TEMPLATE/config.yml.hbs +32 -0
- package/assets/project-setup/templates/.github/ISSUE_TEMPLATE/feature_request.yml.hbs +134 -0
- package/assets/project-setup/templates/.github/PULL_REQUEST_TEMPLATE.md.hbs +172 -0
- package/assets/project-setup/templates/.github/labeler.yml.hbs +123 -0
- package/assets/project-setup/templates/.github/release.yml.hbs +51 -0
- package/assets/project-setup/templates/.github/workflows/labeler.yml.hbs +21 -0
- package/assets/project-setup/templates/.github/workflows/scorecard.yml.hbs +71 -0
- package/assets/project-setup/templates/.github/workflows/stale.yml.hbs +57 -0
- package/dist/core/ai-provider-factory.d.ts.map +1 -1
- package/dist/core/ai-provider-factory.js +22 -5
- package/dist/core/ai-provider.interface.d.ts +16 -0
- package/dist/core/ai-provider.interface.d.ts.map +1 -1
- package/dist/core/capability-scan-workflow.d.ts +4 -9
- package/dist/core/capability-scan-workflow.d.ts.map +1 -1
- package/dist/core/capability-scan-workflow.js +203 -456
- package/dist/core/discovery.d.ts +6 -0
- package/dist/core/discovery.d.ts.map +1 -1
- package/dist/core/discovery.js +39 -3
- package/dist/core/embedding-service.d.ts +9 -36
- package/dist/core/embedding-service.d.ts.map +1 -1
- package/dist/core/embedding-service.js +137 -246
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +2 -2
- package/dist/core/kubernetes-utils.d.ts +1 -0
- package/dist/core/kubernetes-utils.d.ts.map +1 -1
- package/dist/core/kubernetes-utils.js +53 -48
- package/dist/core/model-config.d.ts +2 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +3 -1
- package/dist/core/providers/anthropic-provider.d.ts.map +1 -1
- package/dist/core/providers/anthropic-provider.js +352 -282
- package/dist/core/providers/provider-debug-utils.d.ts +4 -0
- package/dist/core/providers/provider-debug-utils.d.ts.map +1 -1
- package/dist/core/providers/provider-debug-utils.js +25 -3
- package/dist/core/providers/vercel-provider.d.ts +1 -0
- package/dist/core/providers/vercel-provider.d.ts.map +1 -1
- package/dist/core/providers/vercel-provider.js +412 -345
- package/dist/core/tracing/ai-tracing.d.ts +80 -0
- package/dist/core/tracing/ai-tracing.d.ts.map +1 -0
- package/dist/core/tracing/ai-tracing.js +122 -0
- package/dist/core/tracing/config.d.ts +15 -0
- package/dist/core/tracing/config.d.ts.map +1 -0
- package/dist/core/tracing/config.js +133 -0
- package/dist/core/tracing/http-tracing.d.ts +28 -0
- package/dist/core/tracing/http-tracing.d.ts.map +1 -0
- package/dist/core/tracing/http-tracing.js +119 -0
- package/dist/core/tracing/index.d.ts +14 -0
- package/dist/core/tracing/index.d.ts.map +1 -0
- package/dist/core/tracing/index.js +40 -0
- package/dist/core/tracing/k8s-tracing.d.ts +57 -0
- package/dist/core/tracing/k8s-tracing.d.ts.map +1 -0
- package/dist/core/tracing/k8s-tracing.js +155 -0
- package/dist/core/tracing/qdrant-tracing.d.ts +68 -0
- package/dist/core/tracing/qdrant-tracing.d.ts.map +1 -0
- package/dist/core/tracing/qdrant-tracing.js +102 -0
- package/dist/core/tracing/tool-tracing.d.ts +31 -0
- package/dist/core/tracing/tool-tracing.d.ts.map +1 -0
- package/dist/core/tracing/tool-tracing.js +76 -0
- package/dist/core/tracing/tracer.d.ts +21 -0
- package/dist/core/tracing/tracer.d.ts.map +1 -0
- package/dist/core/tracing/tracer.js +215 -0
- package/dist/core/tracing/types.d.ts +86 -0
- package/dist/core/tracing/types.d.ts.map +1 -0
- package/dist/core/tracing/types.js +41 -0
- package/dist/core/unified-creation-session.js +1 -1
- package/dist/core/vector-db-service.d.ts.map +1 -1
- package/dist/core/vector-db-service.js +238 -163
- package/dist/interfaces/mcp.d.ts.map +1 -1
- package/dist/interfaces/mcp.js +71 -43
- package/dist/mcp/server.js +12 -2
- package/dist/tools/organizational-data.d.ts.map +1 -1
- package/dist/tools/organizational-data.js +2 -4
- package/dist/tools/version.d.ts +12 -1
- package/dist/tools/version.d.ts.map +1 -1
- package/dist/tools/version.js +24 -4
- 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 ??
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
97
|
-
|
|
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
|
-
|
|
101
|
-
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
|
|
213
|
-
|
|
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
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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
|
-
|
|
297
|
-
|
|
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
|
-
//
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
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;
|