indusagi 0.13.6 → 0.13.8

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 (44) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +7 -1
  3. package/dist/cli.js +114 -14
  4. package/dist/index.js +1618 -51
  5. package/dist/llmgateway.js +114 -14
  6. package/dist/mcp.js +812 -3
  7. package/dist/runtime.js +114 -14
  8. package/dist/sarvam-mcp.js +960 -0
  9. package/dist/shell-app.js +116 -14
  10. package/dist/smithy.js +114 -14
  11. package/dist/swarm.js +114 -14
  12. package/dist/tracing.js +37 -0
  13. package/dist/types/connectors-sarvam/connect.d.ts +14 -0
  14. package/dist/types/connectors-sarvam/connectors-sarvam.test.d.ts +14 -0
  15. package/dist/types/connectors-sarvam/index.d.ts +14 -0
  16. package/dist/types/connectors-sarvam/toolbox.d.ts +19 -0
  17. package/dist/types/connectors-sarvam/types.d.ts +49 -0
  18. package/dist/types/connectors-zoho/connect.d.ts +22 -0
  19. package/dist/types/connectors-zoho/connectors-zoho.test.d.ts +10 -0
  20. package/dist/types/connectors-zoho/index.d.ts +13 -0
  21. package/dist/types/connectors-zoho/toolbox.d.ts +19 -0
  22. package/dist/types/connectors-zoho/types.d.ts +56 -0
  23. package/dist/types/facade/mcp-core/client.d.ts +32 -0
  24. package/dist/types/facade/mcp-core/index.d.ts +4 -0
  25. package/dist/types/facade/mcp-core/oauth/flow.d.ts +72 -0
  26. package/dist/types/facade/mcp-core/oauth/index.d.ts +18 -0
  27. package/dist/types/facade/mcp-core/oauth/oauth.test.d.ts +8 -0
  28. package/dist/types/facade/mcp-core/oauth/provider.d.ts +51 -0
  29. package/dist/types/facade/mcp-core/oauth/token-store.d.ts +31 -0
  30. package/dist/types/facade/mcp-core/oauth/types.d.ts +96 -0
  31. package/dist/types/facade/mcp-core/toolbox-bridge.d.ts +46 -0
  32. package/dist/types/facade/mcp-core/toolbox-bridge.test.d.ts +8 -0
  33. package/dist/types/index.d.ts +2 -0
  34. package/dist/types/llmgateway/contract/model-card.d.ts +1 -1
  35. package/dist/types/llmgateway/credentials/secrets.d.ts +2 -0
  36. package/dist/zoho.js +1451 -0
  37. package/package.json +11 -4
  38. package/dist/knowledge/guides/authoring-an-agent.md +0 -53
  39. package/dist/knowledge/guides/choosing-tools.md +0 -49
  40. package/dist/knowledge/guides/model-selection.md +0 -51
  41. package/dist/knowledge/guides/writing-system-prompts.md +0 -53
  42. package/dist/knowledge/index.ts +0 -19
  43. package/dist/knowledge/loader.ts +0 -200
  44. package/dist/knowledge/manifest.json +0 -29
package/dist/shell-app.js CHANGED
@@ -476,6 +476,85 @@ var MODEL_CARDS = [
476
476
  cacheReadPerMTok: 0.15
477
477
  }
478
478
  },
479
+ // ── MiniMax (Anthropic-compatible Messages API) ─────────────────────────
480
+ // Wire: same dialect as Claude (`anthropic-messages`) at api.minimax.io.
481
+ // Auth: MINIMAX_API_KEY. Ids match facade/models.generated.ts.
482
+ {
483
+ id: "MiniMax-M2",
484
+ provider: "minimax",
485
+ api: "anthropic-messages",
486
+ displayName: "MiniMax M2",
487
+ baseUrl: "https://api.minimax.io/anthropic",
488
+ contextWindow: 204800,
489
+ maxOutputTokens: 131072,
490
+ modalities: ["text"],
491
+ reasoning: true,
492
+ cost: {
493
+ inputPerMTok: 0.3,
494
+ outputPerMTok: 1.2
495
+ }
496
+ },
497
+ {
498
+ id: "MiniMax-M2.1",
499
+ provider: "minimax",
500
+ api: "anthropic-messages",
501
+ displayName: "MiniMax M2.1",
502
+ baseUrl: "https://api.minimax.io/anthropic",
503
+ contextWindow: 204800,
504
+ maxOutputTokens: 131072,
505
+ modalities: ["text"],
506
+ reasoning: true,
507
+ cost: {
508
+ inputPerMTok: 0.3,
509
+ outputPerMTok: 1.2
510
+ }
511
+ },
512
+ {
513
+ id: "MiniMax-M2.5",
514
+ provider: "minimax",
515
+ api: "anthropic-messages",
516
+ displayName: "MiniMax M2.5",
517
+ baseUrl: "https://api.minimax.io/anthropic",
518
+ contextWindow: 204800,
519
+ maxOutputTokens: 131072,
520
+ modalities: ["text"],
521
+ reasoning: true,
522
+ cost: {
523
+ inputPerMTok: 0.3,
524
+ outputPerMTok: 1.2
525
+ }
526
+ },
527
+ {
528
+ id: "MiniMax-M2.7",
529
+ provider: "minimax",
530
+ api: "anthropic-messages",
531
+ displayName: "MiniMax M2.7",
532
+ baseUrl: "https://api.minimax.io/anthropic",
533
+ contextWindow: 204800,
534
+ maxOutputTokens: 131072,
535
+ modalities: ["text"],
536
+ reasoning: true,
537
+ cost: {
538
+ inputPerMTok: 0.3,
539
+ outputPerMTok: 1.2
540
+ }
541
+ },
542
+ {
543
+ id: "MiniMax-M3",
544
+ provider: "minimax",
545
+ api: "anthropic-messages",
546
+ displayName: "MiniMax M3",
547
+ baseUrl: "https://api.minimax.io/anthropic",
548
+ contextWindow: 1048576,
549
+ maxOutputTokens: 512e3,
550
+ modalities: ["text", "image"],
551
+ reasoning: true,
552
+ cost: {
553
+ inputPerMTok: 0.6,
554
+ outputPerMTok: 2.4,
555
+ cacheReadPerMTok: 0.12
556
+ }
557
+ },
479
558
  // ── Ollama (local; pricing is zero — your own hardware) ─────────────────
480
559
  {
481
560
  id: "llama3.1:8b",
@@ -597,6 +676,19 @@ var SECRET_TABLE = {
597
676
  envVars: ["MOONSHOT_API_KEY", "KIMI_API_KEY"],
598
677
  hint: "Moonshot AI (Kimi) API key."
599
678
  },
679
+ minimax: {
680
+ provider: "minimax",
681
+ scheme: "api-key",
682
+ envVars: ["MINIMAX_API_KEY"],
683
+ hint: "MiniMax global API key (api.minimax.io Anthropic-compatible)."
684
+ },
685
+ "minimax-cn": {
686
+ provider: "minimax-cn",
687
+ scheme: "api-key",
688
+ // Same key often works for both; CN-specific override first when set.
689
+ envVars: ["MINIMAX_CN_API_KEY", "MINIMAX_API_KEY"],
690
+ hint: "MiniMax China API key (api.minimaxi.com Anthropic-compatible)."
691
+ },
600
692
  ollama: {
601
693
  provider: "ollama",
602
694
  scheme: "none",
@@ -1437,7 +1529,7 @@ function endpointFor(model) {
1437
1529
  const base = (model.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
1438
1530
  return `${base}/v1/messages`;
1439
1531
  }
1440
- async function postMessages(url, apiKey, body, signal) {
1532
+ async function postMessages(url, apiKey, body, signal, provider = "anthropic") {
1441
1533
  let response;
1442
1534
  try {
1443
1535
  response = await fetch(url, {
@@ -1452,24 +1544,24 @@ async function postMessages(url, apiKey, body, signal) {
1452
1544
  });
1453
1545
  } catch (cause) {
1454
1546
  if (signal?.aborted) {
1455
- throw gatewayError("aborted", "request canceled before Anthropic responded", {
1456
- provider: "anthropic",
1547
+ throw gatewayError("aborted", `request canceled before ${provider} responded`, {
1548
+ provider,
1457
1549
  cause
1458
1550
  });
1459
1551
  }
1460
- throw gatewayError("transport", "network call to Anthropic failed", { provider: "anthropic", cause });
1552
+ throw gatewayError("transport", `network call to ${provider} failed`, { provider, cause });
1461
1553
  }
1462
1554
  if (!response.ok) {
1463
1555
  const detail = await readErrorBody(response);
1464
1556
  const kind = response.status === 401 || response.status === 403 ? "auth" : response.status === 429 ? "rate_limit" : "http";
1465
- throw gatewayError(kind, `Anthropic returned HTTP ${response.status}${detail}`, {
1466
- provider: "anthropic",
1557
+ throw gatewayError(kind, `${provider} returned HTTP ${response.status}${detail}`, {
1558
+ provider,
1467
1559
  status: response.status
1468
1560
  });
1469
1561
  }
1470
1562
  if (response.body === null) {
1471
- throw gatewayError("transport", "Anthropic response arrived with no body", {
1472
- provider: "anthropic",
1563
+ throw gatewayError("transport", `${provider} response arrived with no body`, {
1564
+ provider,
1473
1565
  status: response.status
1474
1566
  });
1475
1567
  }
@@ -1491,11 +1583,13 @@ function asGatewayError(cause) {
1491
1583
  }
1492
1584
  function createanthropicConnector(deps2) {
1493
1585
  const api = "anthropic-messages";
1494
- async function requireKey(options) {
1495
- const key = await deps2.resolveSecret("anthropic", options.apiKey);
1586
+ async function requireKey(model, options) {
1587
+ const provider = model.provider;
1588
+ const key = await deps2.resolveSecret(provider, options.apiKey);
1496
1589
  if (key === void 0 || key === "") {
1497
- throw gatewayError("auth", "no Anthropic API key found (set ANTHROPIC_API_KEY or pass options.apiKey)", {
1498
- provider: "anthropic"
1590
+ const hint = provider === "minimax" || provider === "minimax-cn" ? "set MINIMAX_API_KEY (or MINIMAX_CN_API_KEY for CN) or pass options.apiKey" : "set ANTHROPIC_API_KEY or pass options.apiKey";
1591
+ throw gatewayError("auth", `no API key found for provider "${provider}" (${hint})`, {
1592
+ provider
1499
1593
  });
1500
1594
  }
1501
1595
  return key;
@@ -1504,10 +1598,16 @@ function createanthropicConnector(deps2) {
1504
1598
  return channelOf(async function* run2() {
1505
1599
  const collected = [];
1506
1600
  try {
1507
- const apiKey = await requireKey(options);
1601
+ const apiKey = await requireKey(model, options);
1508
1602
  const body = toAnthropicRequest(conversation, model, options);
1509
1603
  body.stream = true;
1510
- const response = await postMessages(endpointFor(model), apiKey, body, options.signal);
1604
+ const response = await postMessages(
1605
+ endpointFor(model),
1606
+ apiKey,
1607
+ body,
1608
+ options.signal,
1609
+ model.provider
1610
+ );
1511
1611
  const wire = response.body;
1512
1612
  const state = { toolIds: /* @__PURE__ */ new Map(), usage: { inputTokens: 0, outputTokens: 0 } };
1513
1613
  for await (const event of sseEvents(wire, options.signal)) {
@@ -12249,6 +12349,8 @@ var KNOWN_PROVIDERS = [
12249
12349
  "azure",
12250
12350
  "nvidia",
12251
12351
  "kimi",
12352
+ "minimax",
12353
+ "minimax-cn",
12252
12354
  "ollama",
12253
12355
  "mock"
12254
12356
  ];
package/dist/smithy.js CHANGED
@@ -3676,6 +3676,85 @@ var MODEL_CARDS = [
3676
3676
  cacheReadPerMTok: 0.15
3677
3677
  }
3678
3678
  },
3679
+ // ── MiniMax (Anthropic-compatible Messages API) ─────────────────────────
3680
+ // Wire: same dialect as Claude (`anthropic-messages`) at api.minimax.io.
3681
+ // Auth: MINIMAX_API_KEY. Ids match facade/models.generated.ts.
3682
+ {
3683
+ id: "MiniMax-M2",
3684
+ provider: "minimax",
3685
+ api: "anthropic-messages",
3686
+ displayName: "MiniMax M2",
3687
+ baseUrl: "https://api.minimax.io/anthropic",
3688
+ contextWindow: 204800,
3689
+ maxOutputTokens: 131072,
3690
+ modalities: ["text"],
3691
+ reasoning: true,
3692
+ cost: {
3693
+ inputPerMTok: 0.3,
3694
+ outputPerMTok: 1.2
3695
+ }
3696
+ },
3697
+ {
3698
+ id: "MiniMax-M2.1",
3699
+ provider: "minimax",
3700
+ api: "anthropic-messages",
3701
+ displayName: "MiniMax M2.1",
3702
+ baseUrl: "https://api.minimax.io/anthropic",
3703
+ contextWindow: 204800,
3704
+ maxOutputTokens: 131072,
3705
+ modalities: ["text"],
3706
+ reasoning: true,
3707
+ cost: {
3708
+ inputPerMTok: 0.3,
3709
+ outputPerMTok: 1.2
3710
+ }
3711
+ },
3712
+ {
3713
+ id: "MiniMax-M2.5",
3714
+ provider: "minimax",
3715
+ api: "anthropic-messages",
3716
+ displayName: "MiniMax M2.5",
3717
+ baseUrl: "https://api.minimax.io/anthropic",
3718
+ contextWindow: 204800,
3719
+ maxOutputTokens: 131072,
3720
+ modalities: ["text"],
3721
+ reasoning: true,
3722
+ cost: {
3723
+ inputPerMTok: 0.3,
3724
+ outputPerMTok: 1.2
3725
+ }
3726
+ },
3727
+ {
3728
+ id: "MiniMax-M2.7",
3729
+ provider: "minimax",
3730
+ api: "anthropic-messages",
3731
+ displayName: "MiniMax M2.7",
3732
+ baseUrl: "https://api.minimax.io/anthropic",
3733
+ contextWindow: 204800,
3734
+ maxOutputTokens: 131072,
3735
+ modalities: ["text"],
3736
+ reasoning: true,
3737
+ cost: {
3738
+ inputPerMTok: 0.3,
3739
+ outputPerMTok: 1.2
3740
+ }
3741
+ },
3742
+ {
3743
+ id: "MiniMax-M3",
3744
+ provider: "minimax",
3745
+ api: "anthropic-messages",
3746
+ displayName: "MiniMax M3",
3747
+ baseUrl: "https://api.minimax.io/anthropic",
3748
+ contextWindow: 1048576,
3749
+ maxOutputTokens: 512e3,
3750
+ modalities: ["text", "image"],
3751
+ reasoning: true,
3752
+ cost: {
3753
+ inputPerMTok: 0.6,
3754
+ outputPerMTok: 2.4,
3755
+ cacheReadPerMTok: 0.12
3756
+ }
3757
+ },
3679
3758
  // ── Ollama (local; pricing is zero — your own hardware) ─────────────────
3680
3759
  {
3681
3760
  id: "llama3.1:8b",
@@ -3781,6 +3860,19 @@ var SECRET_TABLE = {
3781
3860
  envVars: ["MOONSHOT_API_KEY", "KIMI_API_KEY"],
3782
3861
  hint: "Moonshot AI (Kimi) API key."
3783
3862
  },
3863
+ minimax: {
3864
+ provider: "minimax",
3865
+ scheme: "api-key",
3866
+ envVars: ["MINIMAX_API_KEY"],
3867
+ hint: "MiniMax global API key (api.minimax.io Anthropic-compatible)."
3868
+ },
3869
+ "minimax-cn": {
3870
+ provider: "minimax-cn",
3871
+ scheme: "api-key",
3872
+ // Same key often works for both; CN-specific override first when set.
3873
+ envVars: ["MINIMAX_CN_API_KEY", "MINIMAX_API_KEY"],
3874
+ hint: "MiniMax China API key (api.minimaxi.com Anthropic-compatible)."
3875
+ },
3784
3876
  ollama: {
3785
3877
  provider: "ollama",
3786
3878
  scheme: "none",
@@ -4621,7 +4713,7 @@ function endpointFor(model) {
4621
4713
  const base = (model.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
4622
4714
  return `${base}/v1/messages`;
4623
4715
  }
4624
- async function postMessages(url, apiKey, body, signal) {
4716
+ async function postMessages(url, apiKey, body, signal, provider = "anthropic") {
4625
4717
  let response;
4626
4718
  try {
4627
4719
  response = await fetch(url, {
@@ -4636,24 +4728,24 @@ async function postMessages(url, apiKey, body, signal) {
4636
4728
  });
4637
4729
  } catch (cause) {
4638
4730
  if (signal?.aborted) {
4639
- throw gatewayError("aborted", "request canceled before Anthropic responded", {
4640
- provider: "anthropic",
4731
+ throw gatewayError("aborted", `request canceled before ${provider} responded`, {
4732
+ provider,
4641
4733
  cause
4642
4734
  });
4643
4735
  }
4644
- throw gatewayError("transport", "network call to Anthropic failed", { provider: "anthropic", cause });
4736
+ throw gatewayError("transport", `network call to ${provider} failed`, { provider, cause });
4645
4737
  }
4646
4738
  if (!response.ok) {
4647
4739
  const detail = await readErrorBody(response);
4648
4740
  const kind = response.status === 401 || response.status === 403 ? "auth" : response.status === 429 ? "rate_limit" : "http";
4649
- throw gatewayError(kind, `Anthropic returned HTTP ${response.status}${detail}`, {
4650
- provider: "anthropic",
4741
+ throw gatewayError(kind, `${provider} returned HTTP ${response.status}${detail}`, {
4742
+ provider,
4651
4743
  status: response.status
4652
4744
  });
4653
4745
  }
4654
4746
  if (response.body === null) {
4655
- throw gatewayError("transport", "Anthropic response arrived with no body", {
4656
- provider: "anthropic",
4747
+ throw gatewayError("transport", `${provider} response arrived with no body`, {
4748
+ provider,
4657
4749
  status: response.status
4658
4750
  });
4659
4751
  }
@@ -4675,11 +4767,13 @@ function asGatewayError(cause) {
4675
4767
  }
4676
4768
  function createanthropicConnector(deps2) {
4677
4769
  const api = "anthropic-messages";
4678
- async function requireKey(options) {
4679
- const key = await deps2.resolveSecret("anthropic", options.apiKey);
4770
+ async function requireKey(model, options) {
4771
+ const provider = model.provider;
4772
+ const key = await deps2.resolveSecret(provider, options.apiKey);
4680
4773
  if (key === void 0 || key === "") {
4681
- throw gatewayError("auth", "no Anthropic API key found (set ANTHROPIC_API_KEY or pass options.apiKey)", {
4682
- provider: "anthropic"
4774
+ const hint = provider === "minimax" || provider === "minimax-cn" ? "set MINIMAX_API_KEY (or MINIMAX_CN_API_KEY for CN) or pass options.apiKey" : "set ANTHROPIC_API_KEY or pass options.apiKey";
4775
+ throw gatewayError("auth", `no API key found for provider "${provider}" (${hint})`, {
4776
+ provider
4683
4777
  });
4684
4778
  }
4685
4779
  return key;
@@ -4688,10 +4782,16 @@ function createanthropicConnector(deps2) {
4688
4782
  return channelOf(async function* run2() {
4689
4783
  const collected = [];
4690
4784
  try {
4691
- const apiKey = await requireKey(options);
4785
+ const apiKey = await requireKey(model, options);
4692
4786
  const body = toAnthropicRequest(conversation, model, options);
4693
4787
  body.stream = true;
4694
- const response = await postMessages(endpointFor(model), apiKey, body, options.signal);
4788
+ const response = await postMessages(
4789
+ endpointFor(model),
4790
+ apiKey,
4791
+ body,
4792
+ options.signal,
4793
+ model.provider
4794
+ );
4695
4795
  const wire = response.body;
4696
4796
  const state = { toolIds: /* @__PURE__ */ new Map(), usage: { inputTokens: 0, outputTokens: 0 } };
4697
4797
  for await (const event of sseEvents(wire, options.signal)) {
package/dist/swarm.js CHANGED
@@ -240,6 +240,85 @@ var MODEL_CARDS = [
240
240
  cacheReadPerMTok: 0.15
241
241
  }
242
242
  },
243
+ // ── MiniMax (Anthropic-compatible Messages API) ─────────────────────────
244
+ // Wire: same dialect as Claude (`anthropic-messages`) at api.minimax.io.
245
+ // Auth: MINIMAX_API_KEY. Ids match facade/models.generated.ts.
246
+ {
247
+ id: "MiniMax-M2",
248
+ provider: "minimax",
249
+ api: "anthropic-messages",
250
+ displayName: "MiniMax M2",
251
+ baseUrl: "https://api.minimax.io/anthropic",
252
+ contextWindow: 204800,
253
+ maxOutputTokens: 131072,
254
+ modalities: ["text"],
255
+ reasoning: true,
256
+ cost: {
257
+ inputPerMTok: 0.3,
258
+ outputPerMTok: 1.2
259
+ }
260
+ },
261
+ {
262
+ id: "MiniMax-M2.1",
263
+ provider: "minimax",
264
+ api: "anthropic-messages",
265
+ displayName: "MiniMax M2.1",
266
+ baseUrl: "https://api.minimax.io/anthropic",
267
+ contextWindow: 204800,
268
+ maxOutputTokens: 131072,
269
+ modalities: ["text"],
270
+ reasoning: true,
271
+ cost: {
272
+ inputPerMTok: 0.3,
273
+ outputPerMTok: 1.2
274
+ }
275
+ },
276
+ {
277
+ id: "MiniMax-M2.5",
278
+ provider: "minimax",
279
+ api: "anthropic-messages",
280
+ displayName: "MiniMax M2.5",
281
+ baseUrl: "https://api.minimax.io/anthropic",
282
+ contextWindow: 204800,
283
+ maxOutputTokens: 131072,
284
+ modalities: ["text"],
285
+ reasoning: true,
286
+ cost: {
287
+ inputPerMTok: 0.3,
288
+ outputPerMTok: 1.2
289
+ }
290
+ },
291
+ {
292
+ id: "MiniMax-M2.7",
293
+ provider: "minimax",
294
+ api: "anthropic-messages",
295
+ displayName: "MiniMax M2.7",
296
+ baseUrl: "https://api.minimax.io/anthropic",
297
+ contextWindow: 204800,
298
+ maxOutputTokens: 131072,
299
+ modalities: ["text"],
300
+ reasoning: true,
301
+ cost: {
302
+ inputPerMTok: 0.3,
303
+ outputPerMTok: 1.2
304
+ }
305
+ },
306
+ {
307
+ id: "MiniMax-M3",
308
+ provider: "minimax",
309
+ api: "anthropic-messages",
310
+ displayName: "MiniMax M3",
311
+ baseUrl: "https://api.minimax.io/anthropic",
312
+ contextWindow: 1048576,
313
+ maxOutputTokens: 512e3,
314
+ modalities: ["text", "image"],
315
+ reasoning: true,
316
+ cost: {
317
+ inputPerMTok: 0.6,
318
+ outputPerMTok: 2.4,
319
+ cacheReadPerMTok: 0.12
320
+ }
321
+ },
243
322
  // ── Ollama (local; pricing is zero — your own hardware) ─────────────────
244
323
  {
245
324
  id: "llama3.1:8b",
@@ -345,6 +424,19 @@ var SECRET_TABLE = {
345
424
  envVars: ["MOONSHOT_API_KEY", "KIMI_API_KEY"],
346
425
  hint: "Moonshot AI (Kimi) API key."
347
426
  },
427
+ minimax: {
428
+ provider: "minimax",
429
+ scheme: "api-key",
430
+ envVars: ["MINIMAX_API_KEY"],
431
+ hint: "MiniMax global API key (api.minimax.io Anthropic-compatible)."
432
+ },
433
+ "minimax-cn": {
434
+ provider: "minimax-cn",
435
+ scheme: "api-key",
436
+ // Same key often works for both; CN-specific override first when set.
437
+ envVars: ["MINIMAX_CN_API_KEY", "MINIMAX_API_KEY"],
438
+ hint: "MiniMax China API key (api.minimaxi.com Anthropic-compatible)."
439
+ },
348
440
  ollama: {
349
441
  provider: "ollama",
350
442
  scheme: "none",
@@ -1185,7 +1277,7 @@ function endpointFor(model) {
1185
1277
  const base = (model.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
1186
1278
  return `${base}/v1/messages`;
1187
1279
  }
1188
- async function postMessages(url, apiKey, body, signal) {
1280
+ async function postMessages(url, apiKey, body, signal, provider = "anthropic") {
1189
1281
  let response;
1190
1282
  try {
1191
1283
  response = await fetch(url, {
@@ -1200,24 +1292,24 @@ async function postMessages(url, apiKey, body, signal) {
1200
1292
  });
1201
1293
  } catch (cause) {
1202
1294
  if (signal?.aborted) {
1203
- throw gatewayError("aborted", "request canceled before Anthropic responded", {
1204
- provider: "anthropic",
1295
+ throw gatewayError("aborted", `request canceled before ${provider} responded`, {
1296
+ provider,
1205
1297
  cause
1206
1298
  });
1207
1299
  }
1208
- throw gatewayError("transport", "network call to Anthropic failed", { provider: "anthropic", cause });
1300
+ throw gatewayError("transport", `network call to ${provider} failed`, { provider, cause });
1209
1301
  }
1210
1302
  if (!response.ok) {
1211
1303
  const detail = await readErrorBody(response);
1212
1304
  const kind = response.status === 401 || response.status === 403 ? "auth" : response.status === 429 ? "rate_limit" : "http";
1213
- throw gatewayError(kind, `Anthropic returned HTTP ${response.status}${detail}`, {
1214
- provider: "anthropic",
1305
+ throw gatewayError(kind, `${provider} returned HTTP ${response.status}${detail}`, {
1306
+ provider,
1215
1307
  status: response.status
1216
1308
  });
1217
1309
  }
1218
1310
  if (response.body === null) {
1219
- throw gatewayError("transport", "Anthropic response arrived with no body", {
1220
- provider: "anthropic",
1311
+ throw gatewayError("transport", `${provider} response arrived with no body`, {
1312
+ provider,
1221
1313
  status: response.status
1222
1314
  });
1223
1315
  }
@@ -1239,11 +1331,13 @@ function asGatewayError(cause) {
1239
1331
  }
1240
1332
  function createanthropicConnector(deps2) {
1241
1333
  const api = "anthropic-messages";
1242
- async function requireKey(options) {
1243
- const key = await deps2.resolveSecret("anthropic", options.apiKey);
1334
+ async function requireKey(model, options) {
1335
+ const provider = model.provider;
1336
+ const key = await deps2.resolveSecret(provider, options.apiKey);
1244
1337
  if (key === void 0 || key === "") {
1245
- throw gatewayError("auth", "no Anthropic API key found (set ANTHROPIC_API_KEY or pass options.apiKey)", {
1246
- provider: "anthropic"
1338
+ const hint = provider === "minimax" || provider === "minimax-cn" ? "set MINIMAX_API_KEY (or MINIMAX_CN_API_KEY for CN) or pass options.apiKey" : "set ANTHROPIC_API_KEY or pass options.apiKey";
1339
+ throw gatewayError("auth", `no API key found for provider "${provider}" (${hint})`, {
1340
+ provider
1247
1341
  });
1248
1342
  }
1249
1343
  return key;
@@ -1252,10 +1346,16 @@ function createanthropicConnector(deps2) {
1252
1346
  return channelOf(async function* run2() {
1253
1347
  const collected = [];
1254
1348
  try {
1255
- const apiKey = await requireKey(options);
1349
+ const apiKey = await requireKey(model, options);
1256
1350
  const body = toAnthropicRequest(conversation, model, options);
1257
1351
  body.stream = true;
1258
- const response = await postMessages(endpointFor(model), apiKey, body, options.signal);
1352
+ const response = await postMessages(
1353
+ endpointFor(model),
1354
+ apiKey,
1355
+ body,
1356
+ options.signal,
1357
+ model.provider
1358
+ );
1259
1359
  const wire = response.body;
1260
1360
  const state = { toolIds: /* @__PURE__ */ new Map(), usage: { inputTokens: 0, outputTokens: 0 } };
1261
1361
  for await (const event of sseEvents(wire, options.signal)) {
package/dist/tracing.js CHANGED
@@ -231,6 +231,43 @@ var DEFAULT_SECRET_PATTERNS = Object.freeze([
231
231
  label: "private-key-block-value",
232
232
  // a PEM-armoured private key body
233
233
  value: /-----BEGIN(?:[A-Z ]+)?PRIVATE KEY-----/
234
+ },
235
+ // -----------------------------------------------------------------------
236
+ // MCP / Zoho MCP additions.
237
+ // -----------------------------------------------------------------------
238
+ {
239
+ label: "mcp-url-key-name",
240
+ // mcp_url, mcpUrl, mcp_url_secret, MCP_URL, ZOHO_MCP_URL, ZOHO_MCP_TOKEN, etc.
241
+ key: /(?:mcp[_-]?url|zoho[_-]?mcp|mcp[_-]?token)/i
242
+ },
243
+ {
244
+ label: "pkce-verifier-key-name",
245
+ // code_verifier, codeVerifier, pkce_verifier, etc.
246
+ key: /(?:code[_-]?verifier|pkce[_-]?verifier)/i
247
+ },
248
+ {
249
+ label: "mcp-server-url-value",
250
+ // Zoho MCP URLs — the host is enough to make the URL sensitive.
251
+ value: /\bhttps?:\/\/(?:[A-Za-z0-9-]+\.)*mcp\.zoho\.(?:com|in|eu|net|com\.au|jp)\b[^\s"'<>]*/i
252
+ },
253
+ // -----------------------------------------------------------------------
254
+ // Sarvam MCP additions.
255
+ // -----------------------------------------------------------------------
256
+ {
257
+ label: "sarvam-api-key-key-name",
258
+ // SARVAM_API_KEY, sarvamApiKey, sarvam_api_key
259
+ key: /sarvam[_-]?api[_-]?key/i
260
+ },
261
+ {
262
+ label: "sarvam-api-key-value",
263
+ // dashboard-issued key shape if Sarvam ever uses a prefix; fallback so
264
+ // SARVAM_API_KEY=<anything> gets redacted even if no key pattern matched.
265
+ value: /SARVAM_API_KEY\s*=\s*[^\s"'<>]+/i
266
+ },
267
+ {
268
+ label: "api-subscription-key-header",
269
+ // Sarvam's REST auth header name.
270
+ value: /\bapi-subscription-key\s*[:=]\s*[A-Za-z0-9._~+/-]{8,}=*\b/i
234
271
  }
235
272
  ]);
236
273
  function isContainer(value) {
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Connect to Sarvam AI via the official `uvx sarvam-mcp` stdio server.
3
+ *
4
+ * No OAuth — auth is the `SARVAM_API_KEY` env var. We spawn the subprocess
5
+ * with the SDK-backed {@link MCPClient} (which already supports stdio),
6
+ * list the remote tools, and project them into a runtime {@link ToolBox}
7
+ * via {@link mcpClientToToolBox} using `options.id` (default `"sarvam"`)
8
+ * as the tool-name prefix so two MCP servers can never collide.
9
+ */
10
+ import type { ConnectSarvamMcpOptions, SarvamMcpConnection } from "./types.js";
11
+ /**
12
+ * Open a Sarvam MCP stdio connection and return a ready-to-use toolbox + client.
13
+ */
14
+ export declare function connectSarvamMcp(options: ConnectSarvamMcpOptions): Promise<SarvamMcpConnection>;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Tests for {@link connectSarvamMcp}.
3
+ *
4
+ * A small `FakeMCPClient` stands in for the SDK-backed client. We use
5
+ * `vi.mock` to redirect the `MCPClient` import in `./connect.js` to a
6
+ * factory that returns our fake — no subprocess, no `uvx` download, no
7
+ * Sarvam network call, no monkey-patching of live modules. The mock
8
+ * captures every constructor invocation into a shared holder so the
9
+ * assertions can pin exactly what the connector passed to `new MCPClient`.
10
+ *
11
+ * Mirrors the structure of {@link ../connectors-zoho/connectors-zoho.test.ts}
12
+ * so the two connectors share one test idiom.
13
+ */
14
+ export {};
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Public barrel for the Sarvam MCP connector.
3
+ *
4
+ * - {@link connectSarvamMcp} — the high-level "give me a working toolbox"
5
+ * entry point that takes a Sarvam API key (or env var) and spawns
6
+ * `uvx sarvam-mcp` over stdio.
7
+ * - {@link sarvamToolBoxFromClient} — the lower-level adapter for callers
8
+ * who already hold a connected {@link MCPClient}.
9
+ * - {@link ConnectSarvamMcpOptions} / {@link SarvamMcpConnection} — the
10
+ * public types for those two entry points.
11
+ */
12
+ export { connectSarvamMcp } from "./connect.js";
13
+ export { sarvamToolBoxFromClient } from "./toolbox.js";
14
+ export type { ConnectSarvamMcpOptions, SarvamMcpConnection } from "./types.js";
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Thin re-export wrapper so power users can also import just the toolbox
3
+ * adapter without going through {@link connectSarvamMcp}.
4
+ *
5
+ * `sarvamToolBoxFromClient` is equivalent to
6
+ * `mcpClientToToolBox(client, { namePrefix: options.id ?? "sarvam", ... })`
7
+ * — it just defaults the prefix to the Sarvam id.
8
+ */
9
+ import type { McpToToolBoxOptions } from "../facade/mcp-core/toolbox-bridge.js";
10
+ import type { MCPClient } from "../facade/mcp-core/client.js";
11
+ import type { ToolBox } from "../runtime/contract/index.js";
12
+ /**
13
+ * Wrap a connected {@link MCPClient} as a runtime {@link ToolBox} with a
14
+ * Sarvam-friendly prefix. Equivalent to
15
+ * `mcpClientToToolBox(client, { namePrefix: options.id ?? "sarvam", ... })`.
16
+ */
17
+ export declare function sarvamToolBoxFromClient(client: MCPClient, options?: {
18
+ id?: string;
19
+ } & Omit<McpToToolBoxOptions, "namePrefix">): Promise<ToolBox>;