@probelabs/probe 0.6.0-rc103 → 0.6.0-rc104

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.
@@ -2,6 +2,7 @@
2
2
  import { createAnthropic } from '@ai-sdk/anthropic';
3
3
  import { createOpenAI } from '@ai-sdk/openai';
4
4
  import { createGoogleGenerativeAI } from '@ai-sdk/google';
5
+ import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock';
5
6
  import { streamText } from 'ai';
6
7
  import { randomUUID } from 'crypto';
7
8
  import { EventEmitter } from 'events';
@@ -91,8 +92,14 @@ export class ProbeAgent {
91
92
  this.maxResponseTokens = options.maxResponseTokens || parseInt(process.env.MAX_RESPONSE_TOKENS || '0', 10) || null;
92
93
  this.disableMermaidValidation = !!options.disableMermaidValidation;
93
94
 
94
- // Search configuration
95
- this.allowedFolders = options.path ? [options.path] : [process.cwd()];
95
+ // Search configuration - support both path (single) and allowedFolders (array)
96
+ if (options.allowedFolders && Array.isArray(options.allowedFolders)) {
97
+ this.allowedFolders = options.allowedFolders;
98
+ } else if (options.path) {
99
+ this.allowedFolders = [options.path];
100
+ } else {
101
+ this.allowedFolders = [process.cwd()];
102
+ }
96
103
 
97
104
  // API configuration
98
105
  this.clientApiProvider = options.provider || null;
@@ -186,12 +193,18 @@ export class ProbeAgent {
186
193
  const anthropicApiKey = process.env.ANTHROPIC_API_KEY;
187
194
  const openaiApiKey = process.env.OPENAI_API_KEY;
188
195
  const googleApiKey = process.env.GOOGLE_API_KEY;
196
+ const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID;
197
+ const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
198
+ const awsRegion = process.env.AWS_REGION;
199
+ const awsSessionToken = process.env.AWS_SESSION_TOKEN;
200
+ const awsApiKey = process.env.AWS_BEDROCK_API_KEY;
189
201
 
190
202
  // Get custom API URLs if provided
191
203
  const llmBaseUrl = process.env.LLM_BASE_URL;
192
204
  const anthropicApiUrl = process.env.ANTHROPIC_API_URL || llmBaseUrl;
193
205
  const openaiApiUrl = process.env.OPENAI_API_URL || llmBaseUrl;
194
206
  const googleApiUrl = process.env.GOOGLE_API_URL || llmBaseUrl;
207
+ const awsBedrockBaseUrl = process.env.AWS_BEDROCK_BASE_URL || llmBaseUrl;
195
208
 
196
209
  // Get model override if provided
197
210
  const modelName = process.env.MODEL_NAME;
@@ -200,7 +213,12 @@ export class ProbeAgent {
200
213
  const forceProvider = this.clientApiProvider || (process.env.FORCE_PROVIDER ? process.env.FORCE_PROVIDER.toLowerCase() : null);
201
214
 
202
215
  if (this.debug) {
203
- console.log(`[DEBUG] Available API keys: Anthropic=${!!anthropicApiKey}, OpenAI=${!!openaiApiKey}, Google=${!!googleApiKey}`);
216
+ const hasAwsCredentials = !!(awsAccessKeyId && awsSecretAccessKey && awsRegion);
217
+ const hasAwsApiKey = !!awsApiKey;
218
+ console.log(`[DEBUG] Available API keys: Anthropic=${!!anthropicApiKey}, OpenAI=${!!openaiApiKey}, Google=${!!googleApiKey}, AWS Bedrock=${hasAwsCredentials || hasAwsApiKey}`);
219
+ if (hasAwsCredentials) console.log(`[DEBUG] AWS credentials: AccessKey=${!!awsAccessKeyId}, SecretKey=${!!awsSecretAccessKey}, Region=${awsRegion}, SessionToken=${!!awsSessionToken}`);
220
+ if (hasAwsApiKey) console.log(`[DEBUG] AWS API Key provided`);
221
+ if (awsBedrockBaseUrl) console.log(`[DEBUG] AWS Bedrock base URL: ${awsBedrockBaseUrl}`);
204
222
  console.log(`[DEBUG] Force provider: ${forceProvider || '(not set)'}`);
205
223
  if (modelName) console.log(`[DEBUG] Model override: ${modelName}`);
206
224
  }
@@ -216,6 +234,9 @@ export class ProbeAgent {
216
234
  } else if (forceProvider === 'google' && googleApiKey) {
217
235
  this.initializeGoogleModel(googleApiKey, googleApiUrl, modelName);
218
236
  return;
237
+ } else if (forceProvider === 'bedrock' && ((awsAccessKeyId && awsSecretAccessKey && awsRegion) || awsApiKey)) {
238
+ this.initializeBedrockModel(awsAccessKeyId, awsSecretAccessKey, awsRegion, awsSessionToken, awsApiKey, awsBedrockBaseUrl, modelName);
239
+ return;
219
240
  }
220
241
  console.warn(`WARNING: Forced provider "${forceProvider}" selected but required API key is missing or invalid! Falling back to auto-detection.`);
221
242
  }
@@ -227,8 +248,10 @@ export class ProbeAgent {
227
248
  this.initializeOpenAIModel(openaiApiKey, openaiApiUrl, modelName);
228
249
  } else if (googleApiKey) {
229
250
  this.initializeGoogleModel(googleApiKey, googleApiUrl, modelName);
251
+ } else if ((awsAccessKeyId && awsSecretAccessKey && awsRegion) || awsApiKey) {
252
+ this.initializeBedrockModel(awsAccessKeyId, awsSecretAccessKey, awsRegion, awsSessionToken, awsApiKey, awsBedrockBaseUrl, modelName);
230
253
  } else {
231
- throw new Error('No API key provided. Please set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_API_KEY environment variable.');
254
+ throw new Error('No API key provided. Please set ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY, AWS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION), or AWS_BEDROCK_API_KEY environment variables.');
232
255
  }
233
256
  }
234
257
 
@@ -281,6 +304,46 @@ export class ProbeAgent {
281
304
  }
282
305
  }
283
306
 
307
+ /**
308
+ * Initialize AWS Bedrock model
309
+ */
310
+ initializeBedrockModel(accessKeyId, secretAccessKey, region, sessionToken, apiKey, baseURL, modelName) {
311
+ // Build configuration object, only including defined values
312
+ const config = {};
313
+
314
+ // Authentication - prefer API key if provided, otherwise use AWS credentials
315
+ if (apiKey) {
316
+ config.apiKey = apiKey;
317
+ } else if (accessKeyId && secretAccessKey) {
318
+ config.accessKeyId = accessKeyId;
319
+ config.secretAccessKey = secretAccessKey;
320
+ if (sessionToken) {
321
+ config.sessionToken = sessionToken;
322
+ }
323
+ }
324
+
325
+ // Region is required for AWS credentials but optional for API key
326
+ if (region) {
327
+ config.region = region;
328
+ }
329
+
330
+ // Optional base URL
331
+ if (baseURL) {
332
+ config.baseURL = baseURL;
333
+ }
334
+
335
+ this.provider = createAmazonBedrock(config);
336
+ this.model = modelName || 'anthropic.claude-sonnet-4-20250514-v1:0';
337
+ this.apiType = 'bedrock';
338
+
339
+ if (this.debug) {
340
+ const authMethod = apiKey ? 'API Key' : 'AWS Credentials';
341
+ const regionInfo = region ? ` (Region: ${region})` : '';
342
+ const baseUrlInfo = baseURL ? ` (Base URL: ${baseURL})` : '';
343
+ console.log(`Using AWS Bedrock API with model: ${this.model}${regionInfo} [Auth: ${authMethod}]${baseUrlInfo}`);
344
+ }
345
+ }
346
+
284
347
  /**
285
348
  * Process assistant response content and detect/load image references
286
349
  * @param {string} content - The assistant's response content
@@ -1060,8 +1123,12 @@ When troubleshooting:
1060
1123
  } else if (this.toolImplementations[toolName]) {
1061
1124
  // Execute native tool
1062
1125
  try {
1063
- // Add sessionId to params for tool execution
1064
- const toolParams = { ...params, sessionId: this.sessionId };
1126
+ // Add sessionId and workingDirectory to params for tool execution
1127
+ const toolParams = {
1128
+ ...params,
1129
+ sessionId: this.sessionId,
1130
+ workingDirectory: (this.allowedFolders && this.allowedFolders[0]) || process.cwd()
1131
+ };
1065
1132
 
1066
1133
  // Emit tool start event
1067
1134
  this.events.emit('toolCall', {
@@ -1214,8 +1281,10 @@ Remember: Use proper XML format with BOTH opening and closing tags:
1214
1281
  <parameter>value</parameter>
1215
1282
  </tool_name>
1216
1283
 
1217
- Or for quick completion if your previous response was already correct:
1218
- <attempt_complete>`;
1284
+ Or for quick completion if your previous response was already correct and complete:
1285
+ <attempt_complete>
1286
+
1287
+ IMPORTANT: When using <attempt_complete>, this must be the ONLY content in your response. No additional text, explanations, or other content should be included. This tag signals to reuse your previous response as the final answer.`;
1219
1288
  }
1220
1289
 
1221
1290
  currentMessages.push({
@@ -1733,4 +1802,4 @@ Convert your previous response content into actual JSON data that follows this s
1733
1802
  console.log(`[DEBUG] Agent cancelled for session ${this.sessionId}`);
1734
1803
  }
1735
1804
  }
1736
- }
1805
+ }