@probelabs/probe 0.6.0-rc154 → 0.6.0-rc161

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 (49) hide show
  1. package/README.md +80 -1
  2. package/build/agent/FallbackManager.d.ts +176 -0
  3. package/build/agent/FallbackManager.js +545 -0
  4. package/build/agent/ProbeAgent.d.ts +9 -1
  5. package/build/agent/ProbeAgent.js +218 -10
  6. package/build/agent/RetryManager.d.ts +157 -0
  7. package/build/agent/RetryManager.js +334 -0
  8. package/build/agent/acp/server.js +1 -0
  9. package/build/agent/acp/tools.js +6 -2
  10. package/build/agent/index.js +1814 -355
  11. package/build/agent/probeTool.js +20 -2
  12. package/build/agent/tools.js +16 -0
  13. package/build/delegate.js +326 -201
  14. package/build/downloader.js +46 -17
  15. package/build/extractor.js +12 -12
  16. package/build/index.js +13 -0
  17. package/build/tools/common.js +5 -3
  18. package/build/tools/edit.js +409 -0
  19. package/build/tools/index.js +11 -0
  20. package/build/tools/vercel.js +55 -14
  21. package/build/utils.js +18 -9
  22. package/cjs/agent/ProbeAgent.cjs +2268 -699
  23. package/cjs/index.cjs +75902 -74348
  24. package/package.json +2 -2
  25. package/src/agent/FallbackManager.d.ts +176 -0
  26. package/src/agent/FallbackManager.js +545 -0
  27. package/src/agent/ProbeAgent.d.ts +9 -1
  28. package/src/agent/ProbeAgent.js +218 -10
  29. package/src/agent/RetryManager.d.ts +157 -0
  30. package/src/agent/RetryManager.js +334 -0
  31. package/src/agent/acp/server.js +1 -0
  32. package/src/agent/acp/tools.js +6 -2
  33. package/src/agent/index.js +8 -0
  34. package/src/agent/probeTool.js +20 -2
  35. package/src/agent/tools.js +16 -0
  36. package/src/delegate.js +326 -201
  37. package/src/downloader.js +46 -17
  38. package/src/extractor.js +12 -12
  39. package/src/index.js +13 -0
  40. package/src/tools/common.js +5 -3
  41. package/src/tools/edit.js +409 -0
  42. package/src/tools/index.js +11 -0
  43. package/src/tools/vercel.js +55 -14
  44. package/src/utils.js +18 -9
  45. package/bin/binaries/probe-v0.6.0-rc154-aarch64-apple-darwin.tar.gz +0 -0
  46. package/bin/binaries/probe-v0.6.0-rc154-aarch64-unknown-linux-gnu.tar.gz +0 -0
  47. package/bin/binaries/probe-v0.6.0-rc154-x86_64-apple-darwin.tar.gz +0 -0
  48. package/bin/binaries/probe-v0.6.0-rc154-x86_64-pc-windows-msvc.zip +0 -0
  49. package/bin/binaries/probe-v0.6.0-rc154-x86_64-unknown-linux-gnu.tar.gz +0 -0
@@ -0,0 +1,545 @@
1
+ /**
2
+ * FallbackManager - Handles provider and model fallback configuration
3
+ *
4
+ * Provides flexible fallback strategies for AI API calls:
5
+ * - Same model across different providers (Azure Claude → Bedrock Claude)
6
+ * - Different models on same provider (Claude 3.7 → Claude 3.5)
7
+ * - Cross-provider fallback (Anthropic → OpenAI → Google)
8
+ * - Custom fallback chains with full configuration
9
+ */
10
+
11
+ import { createAnthropic } from '@ai-sdk/anthropic';
12
+ import { createOpenAI } from '@ai-sdk/openai';
13
+ import { createGoogleGenerativeAI } from '@ai-sdk/google';
14
+ import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock';
15
+
16
+ /**
17
+ * Fallback strategies
18
+ */
19
+ export const FALLBACK_STRATEGIES = {
20
+ SAME_MODEL: 'same-model', // Try same model on different providers
21
+ SAME_PROVIDER: 'same-provider', // Try different models on same provider
22
+ ANY: 'any', // Try any available provider/model
23
+ CUSTOM: 'custom' // Use custom provider list
24
+ };
25
+
26
+ /**
27
+ * Provider configuration schema
28
+ * @typedef {Object} ProviderConfig
29
+ * @property {string} provider - Provider name: 'anthropic', 'openai', 'google', 'bedrock'
30
+ * @property {string} [model] - Model name
31
+ * @property {string} [apiKey] - API key
32
+ * @property {string} [baseURL] - Custom API endpoint
33
+ * @property {number} [maxRetries] - Max retries for this provider (overrides global)
34
+ * @property {string} [region] - AWS region (for Bedrock)
35
+ * @property {string} [accessKeyId] - AWS access key ID (for Bedrock)
36
+ * @property {string} [secretAccessKey] - AWS secret access key (for Bedrock)
37
+ * @property {string} [sessionToken] - AWS session token (for Bedrock)
38
+ */
39
+
40
+ /**
41
+ * Default model mappings for each provider
42
+ */
43
+ const DEFAULT_MODELS = {
44
+ anthropic: 'claude-sonnet-4-5-20250929',
45
+ openai: 'gpt-4o',
46
+ google: 'gemini-2.0-flash-exp',
47
+ bedrock: 'anthropic.claude-sonnet-4-20250514-v1:0'
48
+ };
49
+
50
+ /**
51
+ * FallbackManager class for handling provider and model fallback
52
+ */
53
+ export class FallbackManager {
54
+ /**
55
+ * Create a new FallbackManager
56
+ * @param {Object} options - Configuration options
57
+ * @param {string} [options.strategy='any'] - Fallback strategy
58
+ * @param {Array<string>} [options.models] - List of models for same-provider fallback
59
+ * @param {Array<ProviderConfig>} [options.providers] - List of provider configurations
60
+ * @param {boolean} [options.stopOnSuccess=true] - Stop on first success
61
+ * @param {boolean} [options.continueOnNonRetryableError=false] - Continue to fallback on non-retryable errors
62
+ * @param {number} [options.maxTotalAttempts=10] - Maximum total attempts across all providers
63
+ * @param {boolean} [options.debug=false] - Enable debug logging
64
+ */
65
+ constructor(options = {}) {
66
+ this.strategy = options.strategy || FALLBACK_STRATEGIES.ANY;
67
+ this.models = Array.isArray(options.models) ? options.models : [];
68
+ this.providers = Array.isArray(options.providers) ? options.providers : [];
69
+ this.stopOnSuccess = options.stopOnSuccess ?? true;
70
+ this.continueOnNonRetryableError = options.continueOnNonRetryableError ?? false;
71
+ this.debug = options.debug ?? false;
72
+
73
+ // Validate maxTotalAttempts
74
+ const maxAttempts = options.maxTotalAttempts ?? 10;
75
+ if (typeof maxAttempts !== 'number' || isNaN(maxAttempts) || maxAttempts < 1 || maxAttempts > 100) {
76
+ throw new Error(`FallbackManager: maxTotalAttempts must be a number between 1 and 100, got: ${maxAttempts}`);
77
+ }
78
+ this.maxTotalAttempts = maxAttempts;
79
+
80
+ // Statistics
81
+ this.stats = {
82
+ totalAttempts: 0,
83
+ providerAttempts: {},
84
+ successfulProvider: null,
85
+ failedProviders: []
86
+ };
87
+
88
+ // Validate configuration
89
+ this._validateConfiguration();
90
+ }
91
+
92
+ /**
93
+ * Validate the fallback configuration
94
+ * @private
95
+ */
96
+ _validateConfiguration() {
97
+ if (this.strategy === FALLBACK_STRATEGIES.SAME_PROVIDER && this.models.length === 0) {
98
+ throw new Error('FallbackManager: strategy "same-provider" requires models list');
99
+ }
100
+
101
+ if (this.strategy === FALLBACK_STRATEGIES.CUSTOM && this.providers.length === 0) {
102
+ throw new Error('FallbackManager: strategy "custom" requires providers list');
103
+ }
104
+
105
+ // Validate provider configurations
106
+ for (const config of this.providers) {
107
+ if (!config.provider) {
108
+ throw new Error('FallbackManager: Each provider config must have a "provider" field');
109
+ }
110
+
111
+ if (!['anthropic', 'openai', 'google', 'bedrock'].includes(config.provider)) {
112
+ throw new Error(`FallbackManager: Invalid provider "${config.provider}". Must be: anthropic, openai, google, or bedrock`);
113
+ }
114
+
115
+ // Validate Bedrock configuration
116
+ if (config.provider === 'bedrock') {
117
+ const hasCredentials = config.accessKeyId && config.secretAccessKey && config.region;
118
+ const hasApiKey = config.apiKey;
119
+
120
+ if (!hasCredentials && !hasApiKey) {
121
+ throw new Error('FallbackManager: Bedrock provider requires either (accessKeyId, secretAccessKey, region) or apiKey');
122
+ }
123
+ } else {
124
+ // Other providers require apiKey
125
+ if (!config.apiKey) {
126
+ throw new Error(`FallbackManager: Provider "${config.provider}" requires apiKey`);
127
+ }
128
+ }
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Create a provider instance from configuration
134
+ * @param {ProviderConfig} config - Provider configuration
135
+ * @returns {Object} - Provider instance
136
+ * @throws {Error} - If provider creation fails
137
+ * @private
138
+ */
139
+ _createProviderInstance(config) {
140
+ try {
141
+ switch (config.provider) {
142
+ case 'anthropic':
143
+ return createAnthropic({
144
+ apiKey: config.apiKey,
145
+ ...(config.baseURL && { baseURL: config.baseURL })
146
+ });
147
+
148
+ case 'openai':
149
+ return createOpenAI({
150
+ compatibility: 'strict',
151
+ apiKey: config.apiKey,
152
+ ...(config.baseURL && { baseURL: config.baseURL })
153
+ });
154
+
155
+ case 'google':
156
+ return createGoogleGenerativeAI({
157
+ apiKey: config.apiKey,
158
+ ...(config.baseURL && { baseURL: config.baseURL })
159
+ });
160
+
161
+ case 'bedrock': {
162
+ const bedrockConfig = {};
163
+
164
+ if (config.apiKey) {
165
+ bedrockConfig.apiKey = config.apiKey;
166
+ } else if (config.accessKeyId && config.secretAccessKey) {
167
+ bedrockConfig.accessKeyId = config.accessKeyId;
168
+ bedrockConfig.secretAccessKey = config.secretAccessKey;
169
+ if (config.sessionToken) {
170
+ bedrockConfig.sessionToken = config.sessionToken;
171
+ }
172
+ }
173
+
174
+ if (config.region) {
175
+ bedrockConfig.region = config.region;
176
+ }
177
+
178
+ if (config.baseURL) {
179
+ bedrockConfig.baseURL = config.baseURL;
180
+ }
181
+
182
+ return createAmazonBedrock(bedrockConfig);
183
+ }
184
+
185
+ default:
186
+ throw new Error(`FallbackManager: Unknown provider "${config.provider}"`);
187
+ }
188
+ } catch (error) {
189
+ // Re-throw with more context
190
+ const providerName = this._getProviderDisplayName(config);
191
+ throw new Error(`Failed to create provider instance for ${providerName}: ${error.message}`);
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Get the model name for a provider configuration
197
+ * @param {ProviderConfig} config - Provider configuration
198
+ * @returns {string} - Model name
199
+ * @private
200
+ */
201
+ _getModelName(config) {
202
+ return config.model || DEFAULT_MODELS[config.provider];
203
+ }
204
+
205
+ /**
206
+ * Get provider display name for logging
207
+ * @param {ProviderConfig} config - Provider configuration
208
+ * @returns {string} - Display name
209
+ * @private
210
+ */
211
+ _getProviderDisplayName(config) {
212
+ const model = this._getModelName(config);
213
+ const provider = config.provider;
214
+ const url = config.baseURL ? ` (${config.baseURL})` : '';
215
+ return `${provider}/${model}${url}`;
216
+ }
217
+
218
+ /**
219
+ * Execute a function with fallback support
220
+ * @param {Function} fn - Function that takes (provider, model, config) and returns a Promise
221
+ * @returns {Promise<*>} - Result from the function
222
+ * @throws {Error} - If all fallbacks are exhausted
223
+ */
224
+ async executeWithFallback(fn) {
225
+ if (this.providers.length === 0) {
226
+ throw new Error('FallbackManager: No providers configured for fallback');
227
+ }
228
+
229
+ let lastError = null;
230
+ let totalAttempts = 0;
231
+
232
+ for (const config of this.providers) {
233
+ if (totalAttempts >= this.maxTotalAttempts) {
234
+ if (this.debug) {
235
+ console.log(`[FallbackManager] ⚠️ Max total attempts (${this.maxTotalAttempts}) reached`);
236
+ }
237
+ break;
238
+ }
239
+
240
+ totalAttempts++;
241
+ this.stats.totalAttempts++;
242
+
243
+ const providerName = this._getProviderDisplayName(config);
244
+ this.stats.providerAttempts[providerName] = (this.stats.providerAttempts[providerName] || 0) + 1;
245
+
246
+ try {
247
+ if (this.debug) {
248
+ console.log(`[FallbackManager] Attempting provider: ${providerName} (attempt ${totalAttempts}/${this.maxTotalAttempts})`);
249
+ }
250
+
251
+ const provider = this._createProviderInstance(config);
252
+ const model = this._getModelName(config);
253
+
254
+ const result = await fn(provider, model, config);
255
+
256
+ // Success!
257
+ this.stats.successfulProvider = providerName;
258
+
259
+ if (this.debug) {
260
+ console.log(`[FallbackManager] ✅ Success with provider: ${providerName}`);
261
+ }
262
+
263
+ return result;
264
+
265
+ } catch (error) {
266
+ lastError = error;
267
+ const errorInfo = {
268
+ message: error.message || error.toString(),
269
+ type: error.type || error.constructor.name,
270
+ statusCode: error.statusCode || error.status
271
+ };
272
+
273
+ this.stats.failedProviders.push({
274
+ provider: providerName,
275
+ error: errorInfo
276
+ });
277
+
278
+ if (this.debug) {
279
+ console.log(`[FallbackManager] ❌ Failed with provider: ${providerName}`, errorInfo);
280
+ }
281
+
282
+ // Check if we should continue to next provider
283
+ // If error is not retryable and continueOnNonRetryableError is false, stop
284
+ if (!this.continueOnNonRetryableError && error.nonRetryable) {
285
+ if (this.debug) {
286
+ console.log(`[FallbackManager] Non-retryable error, stopping fallback chain`);
287
+ }
288
+ throw error;
289
+ }
290
+
291
+ // Continue to next provider
292
+ if (this.debug) {
293
+ const remaining = this.providers.length - (this.providers.indexOf(config) + 1);
294
+ console.log(`[FallbackManager] Trying next provider (${remaining} remaining)...`);
295
+ }
296
+ }
297
+ }
298
+
299
+ // All providers failed
300
+ if (this.debug) {
301
+ console.log(`[FallbackManager] ❌ All providers exhausted. Total attempts: ${totalAttempts}`);
302
+ }
303
+
304
+ // Enhance error with fallback context
305
+ const fallbackError = new Error(
306
+ `All provider fallbacks exhausted after ${totalAttempts} attempts. Last error: ${lastError?.message || 'Unknown error'}`
307
+ );
308
+ fallbackError.cause = lastError;
309
+ fallbackError.stats = this.getStats();
310
+ fallbackError.allProvidersFailed = true;
311
+
312
+ throw fallbackError;
313
+ }
314
+
315
+ /**
316
+ * Get fallback statistics
317
+ * @returns {Object} - Statistics object
318
+ */
319
+ getStats() {
320
+ return {
321
+ ...this.stats,
322
+ providerAttempts: { ...this.stats.providerAttempts },
323
+ failedProviders: [...this.stats.failedProviders]
324
+ };
325
+ }
326
+
327
+ /**
328
+ * Reset statistics
329
+ */
330
+ resetStats() {
331
+ this.stats = {
332
+ totalAttempts: 0,
333
+ providerAttempts: {},
334
+ successfulProvider: null,
335
+ failedProviders: []
336
+ };
337
+ }
338
+ }
339
+
340
+ /**
341
+ * Create a FallbackManager from environment variables
342
+ * @param {boolean} [debug=false] - Enable debug logging
343
+ * @returns {FallbackManager|null} - Configured FallbackManager instance or null if no fallback config
344
+ */
345
+ export function createFallbackManagerFromEnv(debug = false) {
346
+ const fallbackProvidersEnv = process.env.FALLBACK_PROVIDERS;
347
+ const fallbackModelsEnv = process.env.FALLBACK_MODELS;
348
+
349
+ // If no fallback configuration, return null
350
+ if (!fallbackProvidersEnv && !fallbackModelsEnv) {
351
+ return null;
352
+ }
353
+
354
+ let providers = [];
355
+ let models = [];
356
+ let strategy = FALLBACK_STRATEGIES.ANY;
357
+
358
+ // Parse providers configuration
359
+ if (fallbackProvidersEnv) {
360
+ try {
361
+ // Validate input is a string and not suspiciously long
362
+ if (typeof fallbackProvidersEnv !== 'string' || fallbackProvidersEnv.length > 10000) {
363
+ console.error('[FallbackManager] FALLBACK_PROVIDERS must be a valid JSON string under 10KB');
364
+ return null;
365
+ }
366
+
367
+ const parsed = JSON.parse(fallbackProvidersEnv);
368
+
369
+ // Validate parsed result is an array
370
+ if (!Array.isArray(parsed)) {
371
+ console.error('[FallbackManager] FALLBACK_PROVIDERS must be a JSON array');
372
+ return null;
373
+ }
374
+
375
+ providers = parsed;
376
+ strategy = FALLBACK_STRATEGIES.CUSTOM;
377
+ } catch (error) {
378
+ console.error('[FallbackManager] Failed to parse FALLBACK_PROVIDERS:', error.message);
379
+ return null;
380
+ }
381
+ }
382
+
383
+ // Parse models configuration
384
+ if (fallbackModelsEnv) {
385
+ try {
386
+ // Validate input is a string and not suspiciously long
387
+ if (typeof fallbackModelsEnv !== 'string' || fallbackModelsEnv.length > 10000) {
388
+ console.error('[FallbackManager] FALLBACK_MODELS must be a valid JSON string under 10KB');
389
+ return null;
390
+ }
391
+
392
+ const parsed = JSON.parse(fallbackModelsEnv);
393
+
394
+ // Validate parsed result is an array
395
+ if (!Array.isArray(parsed)) {
396
+ console.error('[FallbackManager] FALLBACK_MODELS must be a JSON array');
397
+ return null;
398
+ }
399
+
400
+ models = parsed;
401
+ strategy = FALLBACK_STRATEGIES.SAME_PROVIDER;
402
+ } catch (error) {
403
+ console.error('[FallbackManager] Failed to parse FALLBACK_MODELS:', error.message);
404
+ return null;
405
+ }
406
+ }
407
+
408
+ const maxTotalAttempts = process.env.FALLBACK_MAX_TOTAL_ATTEMPTS
409
+ ? (() => {
410
+ const val = parseInt(process.env.FALLBACK_MAX_TOTAL_ATTEMPTS, 10);
411
+ if (isNaN(val) || val < 1 || val > 100) {
412
+ console.warn('[FallbackManager] FALLBACK_MAX_TOTAL_ATTEMPTS must be between 1 and 100, using default: 10');
413
+ return 10;
414
+ }
415
+ return val;
416
+ })()
417
+ : 10;
418
+
419
+ return new FallbackManager({
420
+ strategy,
421
+ providers,
422
+ models,
423
+ maxTotalAttempts,
424
+ debug
425
+ });
426
+ }
427
+
428
+ /**
429
+ * Build a fallback provider list from current environment
430
+ * @param {Object} options - Options for building the list
431
+ * @param {string} [options.primaryProvider] - Primary provider to try first
432
+ * @param {string} [options.primaryModel] - Primary model to use
433
+ * @returns {Array<ProviderConfig>} - List of provider configurations
434
+ */
435
+ export function buildFallbackProvidersFromEnv(options = {}) {
436
+ const providers = [];
437
+
438
+ // Get all available API keys from environment
439
+ const anthropicApiKey = process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN;
440
+ const openaiApiKey = process.env.OPENAI_API_KEY;
441
+ const googleApiKey = process.env.GOOGLE_GENERATIVE_AI_API_KEY || process.env.GOOGLE_API_KEY;
442
+ const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID;
443
+ const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
444
+ const awsRegion = process.env.AWS_REGION;
445
+ const awsApiKey = process.env.AWS_BEDROCK_API_KEY;
446
+
447
+ // Get custom URLs
448
+ const llmBaseUrl = process.env.LLM_BASE_URL;
449
+ const anthropicApiUrl = process.env.ANTHROPIC_API_URL || process.env.ANTHROPIC_BASE_URL || llmBaseUrl;
450
+ const openaiApiUrl = process.env.OPENAI_API_URL || llmBaseUrl;
451
+ const googleApiUrl = process.env.GOOGLE_API_URL || llmBaseUrl;
452
+ const awsBedrockBaseUrl = process.env.AWS_BEDROCK_BASE_URL || llmBaseUrl;
453
+
454
+ // Build primary provider config
455
+ const primaryProvider = options.primaryProvider?.toLowerCase();
456
+ const primaryModel = options.primaryModel;
457
+
458
+ // Add primary provider first if specified
459
+ if (primaryProvider === 'anthropic' && anthropicApiKey) {
460
+ providers.push({
461
+ provider: 'anthropic',
462
+ apiKey: anthropicApiKey,
463
+ ...(anthropicApiUrl && { baseURL: anthropicApiUrl }),
464
+ ...(primaryModel && { model: primaryModel })
465
+ });
466
+ } else if (primaryProvider === 'openai' && openaiApiKey) {
467
+ providers.push({
468
+ provider: 'openai',
469
+ apiKey: openaiApiKey,
470
+ ...(openaiApiUrl && { baseURL: openaiApiUrl }),
471
+ ...(primaryModel && { model: primaryModel })
472
+ });
473
+ } else if (primaryProvider === 'google' && googleApiKey) {
474
+ providers.push({
475
+ provider: 'google',
476
+ apiKey: googleApiKey,
477
+ ...(googleApiUrl && { baseURL: googleApiUrl }),
478
+ ...(primaryModel && { model: primaryModel })
479
+ });
480
+ } else if (primaryProvider === 'bedrock' && ((awsAccessKeyId && awsSecretAccessKey && awsRegion) || awsApiKey)) {
481
+ const config = { provider: 'bedrock' };
482
+
483
+ if (awsApiKey) {
484
+ config.apiKey = awsApiKey;
485
+ } else {
486
+ config.accessKeyId = awsAccessKeyId;
487
+ config.secretAccessKey = awsSecretAccessKey;
488
+ config.region = awsRegion;
489
+ if (process.env.AWS_SESSION_TOKEN) {
490
+ config.sessionToken = process.env.AWS_SESSION_TOKEN;
491
+ }
492
+ }
493
+
494
+ if (awsBedrockBaseUrl) config.baseURL = awsBedrockBaseUrl;
495
+ if (primaryModel) config.model = primaryModel;
496
+
497
+ providers.push(config);
498
+ }
499
+
500
+ // Add remaining available providers as fallbacks
501
+ if (anthropicApiKey && primaryProvider !== 'anthropic') {
502
+ providers.push({
503
+ provider: 'anthropic',
504
+ apiKey: anthropicApiKey,
505
+ ...(anthropicApiUrl && { baseURL: anthropicApiUrl })
506
+ });
507
+ }
508
+
509
+ if (openaiApiKey && primaryProvider !== 'openai') {
510
+ providers.push({
511
+ provider: 'openai',
512
+ apiKey: openaiApiKey,
513
+ ...(openaiApiUrl && { baseURL: openaiApiUrl })
514
+ });
515
+ }
516
+
517
+ if (googleApiKey && primaryProvider !== 'google') {
518
+ providers.push({
519
+ provider: 'google',
520
+ apiKey: googleApiKey,
521
+ ...(googleApiUrl && { baseURL: googleApiUrl })
522
+ });
523
+ }
524
+
525
+ if (((awsAccessKeyId && awsSecretAccessKey && awsRegion) || awsApiKey) && primaryProvider !== 'bedrock') {
526
+ const config = { provider: 'bedrock' };
527
+
528
+ if (awsApiKey) {
529
+ config.apiKey = awsApiKey;
530
+ } else {
531
+ config.accessKeyId = awsAccessKeyId;
532
+ config.secretAccessKey = awsSecretAccessKey;
533
+ config.region = awsRegion;
534
+ if (process.env.AWS_SESSION_TOKEN) {
535
+ config.sessionToken = process.env.AWS_SESSION_TOKEN;
536
+ }
537
+ }
538
+
539
+ if (awsBedrockBaseUrl) config.baseURL = awsBedrockBaseUrl;
540
+
541
+ providers.push(config);
542
+ }
543
+
544
+ return providers;
545
+ }
@@ -1,5 +1,7 @@
1
1
  // TypeScript definitions for ProbeAgent class
2
2
  import { EventEmitter } from 'events';
3
+ import type { RetryOptions } from './RetryManager';
4
+ import type { FallbackOptions } from './FallbackManager';
3
5
 
4
6
  /**
5
7
  * Configuration options for creating a ProbeAgent instance
@@ -13,10 +15,12 @@ export interface ProbeAgentOptions {
13
15
  promptType?: 'code-explorer' | 'engineer' | 'code-review' | 'support' | 'architect';
14
16
  /** Allow the use of the 'implement' tool for code editing */
15
17
  allowEdit?: boolean;
18
+ /** Enable the delegate tool for task distribution to subagents */
19
+ enableDelegate?: boolean;
16
20
  /** Search directory path */
17
21
  path?: string;
18
22
  /** Force specific AI provider */
19
- provider?: 'anthropic' | 'openai' | 'google';
23
+ provider?: 'anthropic' | 'openai' | 'google' | 'bedrock';
20
24
  /** Override model name */
21
25
  model?: string;
22
26
  /** Enable debug mode */
@@ -31,6 +35,10 @@ export interface ProbeAgentOptions {
31
35
  mcpConfig?: any;
32
36
  /** @deprecated Use mcpConfig instead */
33
37
  mcpServers?: any[];
38
+ /** Retry configuration for handling transient API failures */
39
+ retry?: RetryOptions;
40
+ /** Fallback configuration for multi-provider support */
41
+ fallback?: FallbackOptions | { auto: boolean };
34
42
  }
35
43
 
36
44
  /**