@perstack/runtime 0.0.71 → 0.0.74

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.
@@ -12,17 +12,17 @@ import { createVertex } from '@ai-sdk/google-vertex';
12
12
  import { createOpenAI } from '@ai-sdk/openai';
13
13
  import { createOllama } from 'ollama-ai-provider-v2';
14
14
  import { ProxyAgent, fetch } from 'undici';
15
- import { ApiV1Client } from '@perstack/api-client/v1';
15
+ import { createApiClient } from '@perstack/api-client';
16
16
  import { setup, assign, createActor } from 'xstate';
17
17
  import { readFile } from 'fs/promises';
18
18
  import { createId } from '@paralleldrive/cuid2';
19
19
  import { dedent } from 'ts-dedent';
20
- import { generateText, streamText } from 'ai';
20
+ import { APICallError, generateText, streamText } from 'ai';
21
21
 
22
22
  // package.json
23
23
  var package_default = {
24
24
  name: "@perstack/runtime",
25
- version: "0.0.71",
25
+ version: "0.0.74",
26
26
  description: "Perstack Runtime",
27
27
  author: "Wintermute Technologies, Inc.",
28
28
  license: "Apache-2.0",
@@ -63,18 +63,9 @@ var package_default = {
63
63
  "@ai-sdk/openai": "^2.0.0",
64
64
  "@modelcontextprotocol/sdk": "^1.25.1",
65
65
  "@paralleldrive/cuid2": "^3.0.4",
66
- "@perstack/anthropic-provider": "workspace:*",
67
66
  "@perstack/api-client": "workspace:*",
68
67
  "@perstack/base": "workspace:*",
69
- "@perstack/azure-openai-provider": "workspace:*",
70
- "@perstack/bedrock-provider": "workspace:*",
71
68
  "@perstack/core": "workspace:*",
72
- "@perstack/deepseek-provider": "workspace:*",
73
- "@perstack/google-provider": "workspace:*",
74
- "@perstack/ollama-provider": "workspace:*",
75
- "@perstack/openai-provider": "workspace:*",
76
- "@perstack/provider-core": "workspace:*",
77
- "@perstack/vertex-provider": "workspace:*",
78
69
  ai: "^5.0.115",
79
70
  "ollama-ai-provider-v2": "^1.5.5",
80
71
  commander: "^14.0.2",
@@ -85,6 +76,15 @@ var package_default = {
85
76
  xstate: "^5.25.0"
86
77
  },
87
78
  devDependencies: {
79
+ "@perstack/anthropic-provider": "workspace:*",
80
+ "@perstack/azure-openai-provider": "workspace:*",
81
+ "@perstack/bedrock-provider": "workspace:*",
82
+ "@perstack/deepseek-provider": "workspace:*",
83
+ "@perstack/google-provider": "workspace:*",
84
+ "@perstack/ollama-provider": "workspace:*",
85
+ "@perstack/openai-provider": "workspace:*",
86
+ "@perstack/provider-core": "workspace:*",
87
+ "@perstack/vertex-provider": "workspace:*",
88
88
  "@tsconfig/node22": "^22.0.5",
89
89
  "@types/node": "^25.0.3",
90
90
  memfs: "^4.51.1",
@@ -345,12 +345,15 @@ async function resolveExpertToRun(expertKey, experts, clientOptions) {
345
345
  if (experts[expertKey]) {
346
346
  return experts[expertKey];
347
347
  }
348
- const client = new ApiV1Client({
348
+ const client = createApiClient({
349
349
  baseUrl: clientOptions.perstackApiBaseUrl,
350
350
  apiKey: clientOptions.perstackApiKey
351
351
  });
352
- const { expert } = await client.registry.experts.get({ expertKey });
353
- return toRuntimeExpert(expert);
352
+ const result = await client.registry.experts.get(expertKey);
353
+ if (!result.ok) {
354
+ throw new Error(`Failed to resolve expert "${expertKey}": ${result.error.message}`);
355
+ }
356
+ return toRuntimeExpert(result.data);
354
357
  }
355
358
  function toRuntimeExpert(expert) {
356
359
  const skills = Object.fromEntries(
@@ -2276,40 +2279,1066 @@ async function createProviderAdapter(config, options) {
2276
2279
  pendingCreations.set(cacheKey, creationPromise);
2277
2280
  return creationPromise;
2278
2281
  }
2282
+ var BaseProviderAdapter = class {
2283
+ options;
2284
+ constructor(options) {
2285
+ this.options = options;
2286
+ }
2287
+ getProviderTools(_toolNames, _options) {
2288
+ return {};
2289
+ }
2290
+ getProviderOptions(_config) {
2291
+ return void 0;
2292
+ }
2293
+ getReasoningOptions(_budget) {
2294
+ return void 0;
2295
+ }
2296
+ normalizeError(error) {
2297
+ if (error instanceof Error) {
2298
+ return {
2299
+ name: error.name,
2300
+ message: error.message,
2301
+ isRetryable: this.isRetryable(error),
2302
+ provider: this.providerName,
2303
+ originalError: error
2304
+ };
2305
+ }
2306
+ return {
2307
+ name: "UnknownError",
2308
+ message: String(error),
2309
+ isRetryable: false,
2310
+ provider: this.providerName,
2311
+ originalError: error
2312
+ };
2313
+ }
2314
+ isRetryable(error) {
2315
+ if (error instanceof Error) {
2316
+ const retryablePatterns = [
2317
+ /rate limit/i,
2318
+ /timeout/i,
2319
+ /overloaded/i,
2320
+ /service unavailable/i,
2321
+ /internal server error/i,
2322
+ /bad gateway/i,
2323
+ /gateway timeout/i
2324
+ ];
2325
+ return retryablePatterns.some((pattern) => pattern.test(error.message));
2326
+ }
2327
+ return false;
2328
+ }
2329
+ createProxyFetch(proxyUrl) {
2330
+ const agent = new ProxyAgent(proxyUrl);
2331
+ return (input, init) => {
2332
+ return fetch(input, { ...init, dispatcher: agent });
2333
+ };
2334
+ }
2335
+ };
2336
+ function normalizeAnthropicError(error) {
2337
+ if (error instanceof APICallError) {
2338
+ return {
2339
+ name: error.name,
2340
+ message: error.message,
2341
+ statusCode: error.statusCode,
2342
+ isRetryable: isAnthropicRetryable(error),
2343
+ provider: "anthropic",
2344
+ originalError: error
2345
+ };
2346
+ }
2347
+ if (error instanceof Error) {
2348
+ return {
2349
+ name: error.name,
2350
+ message: error.message,
2351
+ isRetryable: isAnthropicRetryable(error),
2352
+ provider: "anthropic",
2353
+ originalError: error
2354
+ };
2355
+ }
2356
+ return {
2357
+ name: "UnknownError",
2358
+ message: String(error),
2359
+ isRetryable: false,
2360
+ provider: "anthropic",
2361
+ originalError: error
2362
+ };
2363
+ }
2364
+ function isAnthropicRetryable(error) {
2365
+ if (error instanceof APICallError) {
2366
+ if (error.isRetryable) return true;
2367
+ const statusCode = error.statusCode;
2368
+ if (statusCode === 429) return true;
2369
+ if (statusCode === 500) return true;
2370
+ if (statusCode === 502) return true;
2371
+ if (statusCode === 503) return true;
2372
+ if (statusCode === 504) return true;
2373
+ }
2374
+ if (error instanceof Error) {
2375
+ const message = error.message.toLowerCase();
2376
+ if (message.includes("rate limit")) return true;
2377
+ if (message.includes("overloaded")) return true;
2378
+ if (message.includes("timeout")) return true;
2379
+ if (message.includes("service unavailable")) return true;
2380
+ }
2381
+ return false;
2382
+ }
2383
+
2384
+ // ../../packages/providers/anthropic/src/skills.ts
2385
+ function convertSkill(skill) {
2386
+ if (skill.type === "builtin") {
2387
+ return {
2388
+ type: "builtin",
2389
+ name: skill.skillId
2390
+ };
2391
+ }
2392
+ try {
2393
+ return {
2394
+ type: "custom",
2395
+ name: skill.name,
2396
+ mcp_config: JSON.parse(skill.definition)
2397
+ };
2398
+ } catch (error) {
2399
+ throw new Error(
2400
+ `Invalid JSON in custom skill definition for "${skill.name}": ${error instanceof Error ? error.message : String(error)}`
2401
+ );
2402
+ }
2403
+ }
2404
+ function buildProviderOptions(skills) {
2405
+ if (!skills || skills.length === 0) {
2406
+ return void 0;
2407
+ }
2408
+ return {
2409
+ anthropic: {
2410
+ container: {
2411
+ skills: skills.map(convertSkill)
2412
+ }
2413
+ }
2414
+ };
2415
+ }
2416
+
2417
+ // ../../packages/providers/anthropic/src/tools.ts
2418
+ function buildAnthropicTools(client, toolNames, options) {
2419
+ const tools = {};
2420
+ for (const name of toolNames) {
2421
+ switch (name) {
2422
+ case "webSearch": {
2423
+ const webSearchTool = client.tools.webSearch_20250305({
2424
+ maxUses: options?.webSearch?.maxUses,
2425
+ allowedDomains: options?.webSearch?.allowedDomains
2426
+ });
2427
+ tools["web_search"] = webSearchTool;
2428
+ break;
2429
+ }
2430
+ case "webFetch": {
2431
+ const webFetchTool = client.tools.webFetch_20250910({
2432
+ maxUses: options?.webFetch?.maxUses
2433
+ });
2434
+ tools["web_fetch"] = webFetchTool;
2435
+ break;
2436
+ }
2437
+ case "codeExecution": {
2438
+ const codeExecutionTool = client.tools.codeExecution_20250522();
2439
+ tools["code_execution"] = codeExecutionTool;
2440
+ break;
2441
+ }
2442
+ }
2443
+ }
2444
+ return tools;
2445
+ }
2446
+
2447
+ // ../../packages/providers/anthropic/src/adapter.ts
2448
+ var AnthropicProviderAdapter = class extends BaseProviderAdapter {
2449
+ constructor(config, options) {
2450
+ super(options);
2451
+ this.config = config;
2452
+ this.client = createAnthropic({
2453
+ apiKey: config.apiKey,
2454
+ baseURL: config.baseUrl,
2455
+ headers: config.headers,
2456
+ fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
2457
+ });
2458
+ }
2459
+ providerName = "anthropic";
2460
+ client;
2461
+ createModel(modelId) {
2462
+ return this.client(modelId);
2463
+ }
2464
+ getProviderTools(toolNames, options) {
2465
+ return buildAnthropicTools(this.client, toolNames, options);
2466
+ }
2467
+ getProviderOptions(config) {
2468
+ return buildProviderOptions(config?.skills);
2469
+ }
2470
+ getReasoningOptions(budget) {
2471
+ const budgetTokens = this.budgetToTokens(budget);
2472
+ return {
2473
+ anthropic: {
2474
+ thinking: { type: "enabled", budgetTokens }
2475
+ }
2476
+ };
2477
+ }
2478
+ budgetToTokens(budget) {
2479
+ if (typeof budget === "number") return budget;
2480
+ const map = {
2481
+ minimal: 1024,
2482
+ low: 2048,
2483
+ medium: 5e3,
2484
+ high: 1e4
2485
+ };
2486
+ return map[budget] ?? 5e3;
2487
+ }
2488
+ normalizeError(error) {
2489
+ return normalizeAnthropicError(error);
2490
+ }
2491
+ isRetryable(error) {
2492
+ return isAnthropicRetryable(error);
2493
+ }
2494
+ };
2495
+ function normalizeAzureOpenAIError(error) {
2496
+ if (error instanceof APICallError) {
2497
+ return {
2498
+ name: error.name,
2499
+ message: error.message,
2500
+ statusCode: error.statusCode,
2501
+ isRetryable: isAzureOpenAIRetryable(error),
2502
+ provider: "azure-openai",
2503
+ originalError: error
2504
+ };
2505
+ }
2506
+ if (error instanceof Error) {
2507
+ return {
2508
+ name: error.name,
2509
+ message: error.message,
2510
+ isRetryable: isAzureOpenAIRetryable(error),
2511
+ provider: "azure-openai",
2512
+ originalError: error
2513
+ };
2514
+ }
2515
+ return {
2516
+ name: "UnknownError",
2517
+ message: String(error),
2518
+ isRetryable: false,
2519
+ provider: "azure-openai",
2520
+ originalError: error
2521
+ };
2522
+ }
2523
+ function isAzureOpenAIRetryable(error) {
2524
+ if (error instanceof APICallError) {
2525
+ if (error.isRetryable) return true;
2526
+ const statusCode = error.statusCode;
2527
+ if (statusCode === 429) return true;
2528
+ if (statusCode === 500) return true;
2529
+ if (statusCode === 502) return true;
2530
+ if (statusCode === 503) return true;
2531
+ if (statusCode === 504) return true;
2532
+ }
2533
+ if (error instanceof Error) {
2534
+ const message = error.message.toLowerCase();
2535
+ if (message.includes("rate limit")) return true;
2536
+ if (message.includes("timeout")) return true;
2537
+ if (message.includes("service unavailable")) return true;
2538
+ }
2539
+ return false;
2540
+ }
2541
+
2542
+ // ../../packages/providers/azure-openai/src/tools.ts
2543
+ function buildAzureOpenAITools(client, toolNames, options) {
2544
+ const tools = {};
2545
+ for (const name of toolNames) {
2546
+ switch (name) {
2547
+ case "webSearchPreview": {
2548
+ const webSearchTool = client.tools.webSearchPreview({});
2549
+ tools["web_search_preview"] = webSearchTool;
2550
+ break;
2551
+ }
2552
+ case "fileSearch": {
2553
+ const vectorStoreIds = options?.fileSearch?.vectorStoreIds;
2554
+ if (!vectorStoreIds || vectorStoreIds.length === 0) {
2555
+ console.warn(
2556
+ "Azure OpenAI fileSearch tool requires vectorStoreIds. Set providerToolOptions.fileSearch.vectorStoreIds to use this tool."
2557
+ );
2558
+ break;
2559
+ }
2560
+ const fileSearchTool = client.tools.fileSearch({
2561
+ vectorStoreIds,
2562
+ maxNumResults: options?.fileSearch?.maxNumResults
2563
+ });
2564
+ tools["file_search"] = fileSearchTool;
2565
+ break;
2566
+ }
2567
+ case "codeInterpreter": {
2568
+ const codeInterpreterTool = client.tools.codeInterpreter();
2569
+ tools["code_interpreter"] = codeInterpreterTool;
2570
+ break;
2571
+ }
2572
+ case "imageGeneration": {
2573
+ const imageGenerationTool = client.tools.imageGeneration();
2574
+ tools["image_generation"] = imageGenerationTool;
2575
+ break;
2576
+ }
2577
+ }
2578
+ }
2579
+ return tools;
2580
+ }
2581
+
2582
+ // ../../packages/providers/azure-openai/src/adapter.ts
2583
+ var AzureOpenAIProviderAdapter = class extends BaseProviderAdapter {
2584
+ constructor(config, options) {
2585
+ super(options);
2586
+ this.config = config;
2587
+ this.client = createAzure({
2588
+ apiKey: config.apiKey,
2589
+ resourceName: config.resourceName,
2590
+ apiVersion: config.apiVersion,
2591
+ baseURL: config.baseUrl,
2592
+ headers: config.headers,
2593
+ useDeploymentBasedUrls: config.useDeploymentBasedUrls,
2594
+ fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
2595
+ });
2596
+ }
2597
+ providerName = "azure-openai";
2598
+ client;
2599
+ createModel(modelId) {
2600
+ return this.client(modelId);
2601
+ }
2602
+ getProviderTools(toolNames, options) {
2603
+ return buildAzureOpenAITools(this.client, toolNames, options);
2604
+ }
2605
+ normalizeError(error) {
2606
+ return normalizeAzureOpenAIError(error);
2607
+ }
2608
+ isRetryable(error) {
2609
+ return isAzureOpenAIRetryable(error);
2610
+ }
2611
+ };
2612
+ function normalizeBedrockError(error) {
2613
+ if (error instanceof APICallError) {
2614
+ return {
2615
+ name: error.name,
2616
+ message: error.message,
2617
+ statusCode: error.statusCode,
2618
+ isRetryable: isBedrockRetryable(error),
2619
+ provider: "amazon-bedrock",
2620
+ originalError: error
2621
+ };
2622
+ }
2623
+ if (error instanceof Error) {
2624
+ return {
2625
+ name: error.name,
2626
+ message: error.message,
2627
+ isRetryable: isBedrockRetryable(error),
2628
+ provider: "amazon-bedrock",
2629
+ originalError: error
2630
+ };
2631
+ }
2632
+ return {
2633
+ name: "UnknownError",
2634
+ message: String(error),
2635
+ isRetryable: false,
2636
+ provider: "amazon-bedrock",
2637
+ originalError: error
2638
+ };
2639
+ }
2640
+ function isBedrockRetryable(error) {
2641
+ if (error instanceof APICallError) {
2642
+ if (error.isRetryable) return true;
2643
+ const statusCode = error.statusCode;
2644
+ if (statusCode === 429) return true;
2645
+ if (statusCode === 500) return true;
2646
+ if (statusCode === 502) return true;
2647
+ if (statusCode === 503) return true;
2648
+ if (statusCode === 504) return true;
2649
+ }
2650
+ if (error instanceof Error) {
2651
+ const message = error.message.toLowerCase();
2652
+ if (message.includes("rate limit")) return true;
2653
+ if (message.includes("throttl")) return true;
2654
+ if (message.includes("timeout")) return true;
2655
+ if (message.includes("service unavailable")) return true;
2656
+ }
2657
+ return false;
2658
+ }
2659
+
2660
+ // ../../packages/providers/bedrock/src/adapter.ts
2661
+ var BedrockProviderAdapter = class extends BaseProviderAdapter {
2662
+ constructor(config, options) {
2663
+ super(options);
2664
+ this.config = config;
2665
+ this.client = createAmazonBedrock({
2666
+ accessKeyId: config.accessKeyId,
2667
+ secretAccessKey: config.secretAccessKey,
2668
+ region: config.region,
2669
+ sessionToken: config.sessionToken,
2670
+ fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
2671
+ });
2672
+ }
2673
+ providerName = "amazon-bedrock";
2674
+ client;
2675
+ createModel(modelId) {
2676
+ return this.client(modelId);
2677
+ }
2678
+ getProviderOptions(config) {
2679
+ if (!config?.guardrails && !config?.cachePoint) {
2680
+ return void 0;
2681
+ }
2682
+ const bedrockOptions = {};
2683
+ if (config.guardrails) {
2684
+ const guardrailConfig = {
2685
+ guardrailIdentifier: config.guardrails.guardrailIdentifier,
2686
+ guardrailVersion: config.guardrails.guardrailVersion
2687
+ };
2688
+ if (config.guardrails.trace) {
2689
+ guardrailConfig["trace"] = config.guardrails.trace;
2690
+ }
2691
+ bedrockOptions["guardrailConfig"] = guardrailConfig;
2692
+ }
2693
+ if (config.cachePoint) {
2694
+ bedrockOptions["cachePoint"] = { type: config.cachePoint.type };
2695
+ }
2696
+ return { bedrock: bedrockOptions };
2697
+ }
2698
+ getReasoningOptions(budget) {
2699
+ if (budget === "none" || budget === 0) {
2700
+ return void 0;
2701
+ }
2702
+ const budgetTokens = this.budgetToTokens(budget);
2703
+ return {
2704
+ bedrock: {
2705
+ reasoning: {
2706
+ budgetTokens
2707
+ }
2708
+ }
2709
+ };
2710
+ }
2711
+ budgetToTokens(budget) {
2712
+ if (typeof budget === "number") return budget;
2713
+ const map = {
2714
+ minimal: 1024,
2715
+ low: 2048,
2716
+ medium: 5e3,
2717
+ high: 1e4
2718
+ };
2719
+ return map[budget] ?? 5e3;
2720
+ }
2721
+ normalizeError(error) {
2722
+ return normalizeBedrockError(error);
2723
+ }
2724
+ isRetryable(error) {
2725
+ return isBedrockRetryable(error);
2726
+ }
2727
+ };
2728
+ function normalizeDeepSeekError(error) {
2729
+ if (error instanceof APICallError) {
2730
+ return {
2731
+ name: error.name,
2732
+ message: error.message,
2733
+ statusCode: error.statusCode,
2734
+ isRetryable: isDeepSeekRetryable(error),
2735
+ provider: "deepseek",
2736
+ originalError: error
2737
+ };
2738
+ }
2739
+ if (error instanceof Error) {
2740
+ return {
2741
+ name: error.name,
2742
+ message: error.message,
2743
+ isRetryable: isDeepSeekRetryable(error),
2744
+ provider: "deepseek",
2745
+ originalError: error
2746
+ };
2747
+ }
2748
+ return {
2749
+ name: "UnknownError",
2750
+ message: String(error),
2751
+ isRetryable: false,
2752
+ provider: "deepseek",
2753
+ originalError: error
2754
+ };
2755
+ }
2756
+ function isDeepSeekRetryable(error) {
2757
+ if (error instanceof APICallError) {
2758
+ if (error.isRetryable) return true;
2759
+ const statusCode = error.statusCode;
2760
+ if (statusCode === 429) return true;
2761
+ if (statusCode === 500) return true;
2762
+ if (statusCode === 502) return true;
2763
+ if (statusCode === 503) return true;
2764
+ if (statusCode === 504) return true;
2765
+ }
2766
+ if (error instanceof Error) {
2767
+ const message = error.message.toLowerCase();
2768
+ if (message.includes("rate limit")) return true;
2769
+ if (message.includes("timeout")) return true;
2770
+ if (message.includes("service unavailable")) return true;
2771
+ }
2772
+ return false;
2773
+ }
2774
+
2775
+ // ../../packages/providers/deepseek/src/adapter.ts
2776
+ var DeepseekProviderAdapter = class extends BaseProviderAdapter {
2777
+ constructor(config, options) {
2778
+ super(options);
2779
+ this.config = config;
2780
+ this.client = createDeepSeek({
2781
+ apiKey: config.apiKey,
2782
+ baseURL: config.baseUrl,
2783
+ headers: config.headers,
2784
+ fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
2785
+ });
2786
+ }
2787
+ providerName = "deepseek";
2788
+ client;
2789
+ createModel(modelId) {
2790
+ return this.client(modelId);
2791
+ }
2792
+ normalizeError(error) {
2793
+ return normalizeDeepSeekError(error);
2794
+ }
2795
+ isRetryable(error) {
2796
+ return isDeepSeekRetryable(error);
2797
+ }
2798
+ };
2799
+ function normalizeGoogleError(error) {
2800
+ if (error instanceof APICallError) {
2801
+ return {
2802
+ name: error.name,
2803
+ message: error.message,
2804
+ statusCode: error.statusCode,
2805
+ isRetryable: isGoogleRetryable(error),
2806
+ provider: "google",
2807
+ originalError: error
2808
+ };
2809
+ }
2810
+ if (error instanceof Error) {
2811
+ return {
2812
+ name: error.name,
2813
+ message: error.message,
2814
+ isRetryable: isGoogleRetryable(error),
2815
+ provider: "google",
2816
+ originalError: error
2817
+ };
2818
+ }
2819
+ return {
2820
+ name: "UnknownError",
2821
+ message: String(error),
2822
+ isRetryable: false,
2823
+ provider: "google",
2824
+ originalError: error
2825
+ };
2826
+ }
2827
+ function isGoogleRetryable(error) {
2828
+ if (error instanceof APICallError) {
2829
+ if (error.isRetryable) return true;
2830
+ const statusCode = error.statusCode;
2831
+ if (statusCode === 429) return true;
2832
+ if (statusCode === 500) return true;
2833
+ if (statusCode === 502) return true;
2834
+ if (statusCode === 503) return true;
2835
+ if (statusCode === 504) return true;
2836
+ }
2837
+ if (error instanceof Error) {
2838
+ const message = error.message.toLowerCase();
2839
+ if (message.includes("rate limit")) return true;
2840
+ if (message.includes("quota exceeded")) return true;
2841
+ if (message.includes("timeout")) return true;
2842
+ if (message.includes("service unavailable")) return true;
2843
+ }
2844
+ return false;
2845
+ }
2846
+
2847
+ // ../../packages/providers/google/src/tools.ts
2848
+ function buildGoogleTools(client, toolNames, options) {
2849
+ const tools = {};
2850
+ for (const name of toolNames) {
2851
+ switch (name) {
2852
+ case "googleSearch": {
2853
+ const googleSearchTool = client.tools.googleSearch({});
2854
+ tools["google_search"] = googleSearchTool;
2855
+ break;
2856
+ }
2857
+ case "codeExecution": {
2858
+ const codeExecutionTool = client.tools.codeExecution({});
2859
+ tools["code_execution"] = codeExecutionTool;
2860
+ break;
2861
+ }
2862
+ case "urlContext": {
2863
+ const urlContextTool = client.tools.urlContext({});
2864
+ tools["url_context"] = urlContextTool;
2865
+ break;
2866
+ }
2867
+ case "fileSearch": {
2868
+ const storeNames = options?.fileSearch?.vectorStoreIds;
2869
+ if (!storeNames || storeNames.length === 0) {
2870
+ console.warn(
2871
+ "Google fileSearch tool requires fileSearchStoreNames. Set providerToolOptions.fileSearch.vectorStoreIds to use this tool."
2872
+ );
2873
+ break;
2874
+ }
2875
+ const fileSearchTool = client.tools.fileSearch({
2876
+ fileSearchStoreNames: storeNames,
2877
+ topK: options?.fileSearch?.maxNumResults
2878
+ });
2879
+ tools["file_search"] = fileSearchTool;
2880
+ break;
2881
+ }
2882
+ case "googleMaps": {
2883
+ const googleMapsTool = client.tools.googleMaps(options?.googleMaps?.retrievalConfig ?? {});
2884
+ tools["google_maps"] = googleMapsTool;
2885
+ break;
2886
+ }
2887
+ }
2888
+ }
2889
+ return tools;
2890
+ }
2891
+
2892
+ // ../../packages/providers/google/src/adapter.ts
2893
+ var GoogleProviderAdapter = class extends BaseProviderAdapter {
2894
+ constructor(config, options) {
2895
+ super(options);
2896
+ this.config = config;
2897
+ this.client = createGoogleGenerativeAI({
2898
+ apiKey: config.apiKey,
2899
+ baseURL: config.baseUrl,
2900
+ headers: config.headers,
2901
+ fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
2902
+ });
2903
+ }
2904
+ providerName = "google";
2905
+ client;
2906
+ createModel(modelId) {
2907
+ return this.client(modelId);
2908
+ }
2909
+ getProviderTools(toolNames, options) {
2910
+ return buildGoogleTools(this.client, toolNames, options);
2911
+ }
2912
+ normalizeError(error) {
2913
+ return normalizeGoogleError(error);
2914
+ }
2915
+ isRetryable(error) {
2916
+ return isGoogleRetryable(error);
2917
+ }
2918
+ getReasoningOptions(budget) {
2919
+ const budgetTokens = this.budgetToTokens(budget);
2920
+ return {
2921
+ google: {
2922
+ thinkingConfig: {
2923
+ thinkingBudget: budgetTokens,
2924
+ includeThoughts: true
2925
+ }
2926
+ }
2927
+ };
2928
+ }
2929
+ budgetToTokens(budget) {
2930
+ if (typeof budget === "number") return budget;
2931
+ const map = {
2932
+ minimal: 1024,
2933
+ low: 2048,
2934
+ medium: 5e3,
2935
+ high: 1e4
2936
+ };
2937
+ return map[budget] ?? 5e3;
2938
+ }
2939
+ };
2940
+ function normalizeOllamaError(error) {
2941
+ if (error instanceof APICallError) {
2942
+ return {
2943
+ name: error.name,
2944
+ message: error.message,
2945
+ statusCode: error.statusCode,
2946
+ isRetryable: isOllamaRetryable(error),
2947
+ provider: "ollama",
2948
+ originalError: error
2949
+ };
2950
+ }
2951
+ if (error instanceof Error) {
2952
+ return {
2953
+ name: error.name,
2954
+ message: error.message,
2955
+ isRetryable: isOllamaRetryable(error),
2956
+ provider: "ollama",
2957
+ originalError: error
2958
+ };
2959
+ }
2960
+ return {
2961
+ name: "UnknownError",
2962
+ message: String(error),
2963
+ isRetryable: false,
2964
+ provider: "ollama",
2965
+ originalError: error
2966
+ };
2967
+ }
2968
+ function isOllamaRetryable(error) {
2969
+ if (error instanceof APICallError) {
2970
+ if (error.isRetryable) return true;
2971
+ const statusCode = error.statusCode;
2972
+ if (statusCode === 429) return true;
2973
+ if (statusCode === 500) return true;
2974
+ if (statusCode === 502) return true;
2975
+ if (statusCode === 503) return true;
2976
+ if (statusCode === 504) return true;
2977
+ }
2978
+ if (error instanceof Error) {
2979
+ const message = error.message.toLowerCase();
2980
+ if (message.includes("rate limit")) return true;
2981
+ if (message.includes("timeout")) return true;
2982
+ if (message.includes("service unavailable")) return true;
2983
+ if (message.includes("connection refused")) return true;
2984
+ }
2985
+ return false;
2986
+ }
2987
+
2988
+ // ../../packages/providers/ollama/src/adapter.ts
2989
+ var OllamaProviderAdapter = class extends BaseProviderAdapter {
2990
+ constructor(config, options) {
2991
+ super(options);
2992
+ this.config = config;
2993
+ this.client = createOllama({
2994
+ baseURL: config.baseUrl,
2995
+ headers: config.headers,
2996
+ fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
2997
+ });
2998
+ }
2999
+ providerName = "ollama";
3000
+ client;
3001
+ createModel(modelId) {
3002
+ return this.client(modelId);
3003
+ }
3004
+ getProviderOptions(config) {
3005
+ if (config?.think === void 0) {
3006
+ return void 0;
3007
+ }
3008
+ return {
3009
+ ollama: {
3010
+ think: config.think
3011
+ }
3012
+ };
3013
+ }
3014
+ getReasoningOptions(budget) {
3015
+ if (budget === "none" || budget === 0) {
3016
+ return void 0;
3017
+ }
3018
+ return {
3019
+ ollama: {
3020
+ think: true
3021
+ }
3022
+ };
3023
+ }
3024
+ normalizeError(error) {
3025
+ return normalizeOllamaError(error);
3026
+ }
3027
+ isRetryable(error) {
3028
+ return isOllamaRetryable(error);
3029
+ }
3030
+ };
3031
+ function normalizeOpenAIError(error) {
3032
+ if (error instanceof APICallError) {
3033
+ return {
3034
+ name: error.name,
3035
+ message: error.message,
3036
+ statusCode: error.statusCode,
3037
+ isRetryable: isOpenAIRetryable(error),
3038
+ provider: "openai",
3039
+ originalError: error
3040
+ };
3041
+ }
3042
+ if (error instanceof Error) {
3043
+ return {
3044
+ name: error.name,
3045
+ message: error.message,
3046
+ isRetryable: isOpenAIRetryable(error),
3047
+ provider: "openai",
3048
+ originalError: error
3049
+ };
3050
+ }
3051
+ return {
3052
+ name: "UnknownError",
3053
+ message: String(error),
3054
+ isRetryable: false,
3055
+ provider: "openai",
3056
+ originalError: error
3057
+ };
3058
+ }
3059
+ function isOpenAIRetryable(error) {
3060
+ if (error instanceof APICallError) {
3061
+ if (error.isRetryable) return true;
3062
+ const statusCode = error.statusCode;
3063
+ if (statusCode === 429) return true;
3064
+ if (statusCode === 500) return true;
3065
+ if (statusCode === 502) return true;
3066
+ if (statusCode === 503) return true;
3067
+ if (statusCode === 504) return true;
3068
+ }
3069
+ if (error instanceof Error) {
3070
+ const message = error.message.toLowerCase();
3071
+ if (message.includes("rate limit")) return true;
3072
+ if (message.includes("timeout")) return true;
3073
+ if (message.includes("service unavailable")) return true;
3074
+ }
3075
+ return false;
3076
+ }
3077
+
3078
+ // ../../packages/providers/openai/src/tools.ts
3079
+ function buildOpenAITools(client, toolNames, options) {
3080
+ const tools = {};
3081
+ for (const name of toolNames) {
3082
+ switch (name) {
3083
+ case "webSearch": {
3084
+ const webSearchTool = client.tools.webSearch();
3085
+ tools["web_search"] = webSearchTool;
3086
+ break;
3087
+ }
3088
+ case "fileSearch": {
3089
+ const vectorStoreIds = options?.fileSearch?.vectorStoreIds;
3090
+ if (!vectorStoreIds || vectorStoreIds.length === 0) {
3091
+ console.warn(
3092
+ "OpenAI fileSearch tool requires vectorStoreIds. Set providerToolOptions.fileSearch.vectorStoreIds to use this tool."
3093
+ );
3094
+ break;
3095
+ }
3096
+ const fileSearchTool = client.tools.fileSearch({
3097
+ vectorStoreIds,
3098
+ maxNumResults: options?.fileSearch?.maxNumResults
3099
+ });
3100
+ tools["file_search"] = fileSearchTool;
3101
+ break;
3102
+ }
3103
+ case "codeInterpreter": {
3104
+ const codeInterpreterTool = client.tools.codeInterpreter();
3105
+ tools["code_interpreter"] = codeInterpreterTool;
3106
+ break;
3107
+ }
3108
+ case "imageGeneration": {
3109
+ const imageGenerationTool = client.tools.imageGeneration();
3110
+ tools["image_generation"] = imageGenerationTool;
3111
+ break;
3112
+ }
3113
+ }
3114
+ }
3115
+ return tools;
3116
+ }
3117
+
3118
+ // ../../packages/providers/openai/src/adapter.ts
3119
+ var OpenAIProviderAdapter = class extends BaseProviderAdapter {
3120
+ constructor(config, options) {
3121
+ super(options);
3122
+ this.config = config;
3123
+ this.client = createOpenAI({
3124
+ apiKey: config.apiKey,
3125
+ baseURL: config.baseUrl,
3126
+ organization: config.organization,
3127
+ project: config.project,
3128
+ name: config.name,
3129
+ headers: config.headers,
3130
+ fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
3131
+ });
3132
+ }
3133
+ providerName = "openai";
3134
+ client;
3135
+ createModel(modelId) {
3136
+ return this.client(modelId);
3137
+ }
3138
+ getProviderTools(toolNames, options) {
3139
+ return buildOpenAITools(this.client, toolNames, options);
3140
+ }
3141
+ getReasoningOptions(budget) {
3142
+ const effort = this.budgetToEffort(budget);
3143
+ return {
3144
+ openai: { reasoningEffort: effort }
3145
+ };
3146
+ }
3147
+ budgetToEffort(budget) {
3148
+ if (typeof budget === "number") {
3149
+ if (budget <= 2048) return "low";
3150
+ if (budget <= 5e3) return "medium";
3151
+ return "high";
3152
+ }
3153
+ if (budget === "minimal") return "low";
3154
+ return budget;
3155
+ }
3156
+ normalizeError(error) {
3157
+ return normalizeOpenAIError(error);
3158
+ }
3159
+ isRetryable(error) {
3160
+ return isOpenAIRetryable(error);
3161
+ }
3162
+ };
3163
+ function normalizeVertexError(error) {
3164
+ if (error instanceof APICallError) {
3165
+ return {
3166
+ name: error.name,
3167
+ message: error.message,
3168
+ statusCode: error.statusCode,
3169
+ isRetryable: isVertexRetryable(error),
3170
+ provider: "google-vertex",
3171
+ originalError: error
3172
+ };
3173
+ }
3174
+ if (error instanceof Error) {
3175
+ return {
3176
+ name: error.name,
3177
+ message: error.message,
3178
+ isRetryable: isVertexRetryable(error),
3179
+ provider: "google-vertex",
3180
+ originalError: error
3181
+ };
3182
+ }
3183
+ return {
3184
+ name: "UnknownError",
3185
+ message: String(error),
3186
+ isRetryable: false,
3187
+ provider: "google-vertex",
3188
+ originalError: error
3189
+ };
3190
+ }
3191
+ function isVertexRetryable(error) {
3192
+ if (error instanceof APICallError) {
3193
+ if (error.isRetryable) return true;
3194
+ const statusCode = error.statusCode;
3195
+ if (statusCode === 429) return true;
3196
+ if (statusCode === 500) return true;
3197
+ if (statusCode === 502) return true;
3198
+ if (statusCode === 503) return true;
3199
+ if (statusCode === 504) return true;
3200
+ }
3201
+ if (error instanceof Error) {
3202
+ const message = error.message.toLowerCase();
3203
+ if (message.includes("rate limit")) return true;
3204
+ if (message.includes("quota exceeded")) return true;
3205
+ if (message.includes("timeout")) return true;
3206
+ if (message.includes("service unavailable")) return true;
3207
+ }
3208
+ return false;
3209
+ }
3210
+
3211
+ // ../../packages/providers/vertex/src/tools.ts
3212
+ function buildVertexTools(client, toolNames, options) {
3213
+ const tools = {};
3214
+ for (const name of toolNames) {
3215
+ switch (name) {
3216
+ case "googleSearch": {
3217
+ const googleSearchTool = client.tools.googleSearch({});
3218
+ tools["google_search"] = googleSearchTool;
3219
+ break;
3220
+ }
3221
+ case "codeExecution": {
3222
+ const codeExecutionTool = client.tools.codeExecution({});
3223
+ tools["code_execution"] = codeExecutionTool;
3224
+ break;
3225
+ }
3226
+ case "urlContext": {
3227
+ const urlContextTool = client.tools.urlContext({});
3228
+ tools["url_context"] = urlContextTool;
3229
+ break;
3230
+ }
3231
+ case "enterpriseWebSearch": {
3232
+ const enterpriseWebSearchTool = client.tools.enterpriseWebSearch({});
3233
+ tools["enterprise_web_search"] = enterpriseWebSearchTool;
3234
+ break;
3235
+ }
3236
+ case "googleMaps": {
3237
+ const googleMapsTool = client.tools.googleMaps(options?.googleMaps?.retrievalConfig ?? {});
3238
+ tools["google_maps"] = googleMapsTool;
3239
+ break;
3240
+ }
3241
+ }
3242
+ }
3243
+ return tools;
3244
+ }
3245
+
3246
+ // ../../packages/providers/vertex/src/adapter.ts
3247
+ var VertexProviderAdapter = class extends BaseProviderAdapter {
3248
+ constructor(config, options) {
3249
+ super(options);
3250
+ this.config = config;
3251
+ this.client = createVertex({
3252
+ project: config.project,
3253
+ location: config.location,
3254
+ baseURL: config.baseUrl,
3255
+ headers: config.headers,
3256
+ fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
3257
+ });
3258
+ }
3259
+ providerName = "google-vertex";
3260
+ client;
3261
+ createModel(modelId) {
3262
+ return this.client(modelId);
3263
+ }
3264
+ getProviderTools(toolNames, options) {
3265
+ return buildVertexTools(this.client, toolNames, options);
3266
+ }
3267
+ getProviderOptions(config) {
3268
+ if (!config?.safetySettings || config.safetySettings.length === 0) {
3269
+ return void 0;
3270
+ }
3271
+ return {
3272
+ vertex: {
3273
+ safetySettings: config.safetySettings
3274
+ }
3275
+ };
3276
+ }
3277
+ getReasoningOptions(budget) {
3278
+ if (budget === "none" || budget === 0) {
3279
+ return void 0;
3280
+ }
3281
+ const budgetTokens = this.budgetToTokens(budget);
3282
+ return {
3283
+ vertex: {
3284
+ thinkingConfig: {
3285
+ thinkingBudget: budgetTokens,
3286
+ includeThoughts: true
3287
+ }
3288
+ }
3289
+ };
3290
+ }
3291
+ budgetToTokens(budget) {
3292
+ if (typeof budget === "number") return budget;
3293
+ const map = {
3294
+ minimal: 1024,
3295
+ low: 2048,
3296
+ medium: 5e3,
3297
+ high: 1e4
3298
+ };
3299
+ return map[budget] ?? 5e3;
3300
+ }
3301
+ normalizeError(error) {
3302
+ return normalizeVertexError(error);
3303
+ }
3304
+ isRetryable(error) {
3305
+ return isVertexRetryable(error);
3306
+ }
3307
+ };
2279
3308
 
2280
3309
  // src/helpers/register-providers.ts
2281
- registerProviderAdapter("anthropic", async () => {
2282
- const { AnthropicProviderAdapter } = await import('@perstack/anthropic-provider');
2283
- return AnthropicProviderAdapter;
2284
- });
2285
- registerProviderAdapter("openai", async () => {
2286
- const { OpenAIProviderAdapter } = await import('@perstack/openai-provider');
2287
- return OpenAIProviderAdapter;
2288
- });
2289
- registerProviderAdapter("google", async () => {
2290
- const { GoogleProviderAdapter } = await import('@perstack/google-provider');
2291
- return GoogleProviderAdapter;
2292
- });
2293
- registerProviderAdapter("ollama", async () => {
2294
- const { OllamaProviderAdapter } = await import('@perstack/ollama-provider');
2295
- return OllamaProviderAdapter;
2296
- });
2297
- registerProviderAdapter("azure-openai", async () => {
2298
- const { AzureOpenAIProviderAdapter } = await import('@perstack/azure-openai-provider');
2299
- return AzureOpenAIProviderAdapter;
2300
- });
2301
- registerProviderAdapter("amazon-bedrock", async () => {
2302
- const { BedrockProviderAdapter } = await import('@perstack/bedrock-provider');
2303
- return BedrockProviderAdapter;
2304
- });
2305
- registerProviderAdapter("google-vertex", async () => {
2306
- const { VertexProviderAdapter } = await import('@perstack/vertex-provider');
2307
- return VertexProviderAdapter;
2308
- });
2309
- registerProviderAdapter("deepseek", async () => {
2310
- const { DeepseekProviderAdapter } = await import('@perstack/deepseek-provider');
2311
- return DeepseekProviderAdapter;
2312
- });
3310
+ registerProviderAdapter(
3311
+ "anthropic",
3312
+ async () => AnthropicProviderAdapter
3313
+ );
3314
+ registerProviderAdapter(
3315
+ "openai",
3316
+ async () => OpenAIProviderAdapter
3317
+ );
3318
+ registerProviderAdapter(
3319
+ "google",
3320
+ async () => GoogleProviderAdapter
3321
+ );
3322
+ registerProviderAdapter(
3323
+ "ollama",
3324
+ async () => OllamaProviderAdapter
3325
+ );
3326
+ registerProviderAdapter(
3327
+ "azure-openai",
3328
+ async () => AzureOpenAIProviderAdapter
3329
+ );
3330
+ registerProviderAdapter(
3331
+ "amazon-bedrock",
3332
+ async () => BedrockProviderAdapter
3333
+ );
3334
+ registerProviderAdapter(
3335
+ "google-vertex",
3336
+ async () => VertexProviderAdapter
3337
+ );
3338
+ registerProviderAdapter(
3339
+ "deepseek",
3340
+ async () => DeepseekProviderAdapter
3341
+ );
2313
3342
  var shouldEnableReasoning = (budget) => budget !== void 0 && budget !== "none" && budget !== 0;
2314
3343
  var LLMExecutor = class {
2315
3344
  constructor(adapter, model) {
@@ -2636,5 +3665,5 @@ async function run(runInput, options) {
2636
3665
  }
2637
3666
 
2638
3667
  export { findLockfile, getLockfileExpertToolDefinitions, getModel, loadLockfile, package_default, run, runtimeStateMachine };
2639
- //# sourceMappingURL=chunk-LDJKVMQK.js.map
2640
- //# sourceMappingURL=chunk-LDJKVMQK.js.map
3668
+ //# sourceMappingURL=chunk-YZWULND3.js.map
3669
+ //# sourceMappingURL=chunk-YZWULND3.js.map