@stackfactor/agent-utils 1.4.0 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -12
- package/dist/cjs/langChain.d.ts +9 -10
- package/dist/cjs/langChain.d.ts.map +1 -1
- package/dist/cjs/langChain.js +49 -78
- package/dist/esm/langChain.d.ts +9 -10
- package/dist/esm/langChain.d.ts.map +1 -1
- package/dist/esm/langChain.js +49 -78
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
|
|
26
26
|
## `langChain`
|
|
27
27
|
|
|
28
|
-
Unified interface for running LLM prompts, managing LangChain agents, and generating images across OpenAI, Anthropic,
|
|
28
|
+
Unified interface for running LLM prompts, managing LangChain agents, and generating images across the OpenAI, Anthropic, and Google providers.
|
|
29
29
|
|
|
30
30
|
### `langChain.runPromptWithModel(modelName, config, prompt, onProgressReport?, minPercent?, maxPercent?, expectsJsonResponse?, schema?, agentName?, tools?, usageTracker?)`
|
|
31
31
|
|
|
@@ -39,8 +39,8 @@ When `expectsJsonResponse` is `true` (the default), JSON escape instructions are
|
|
|
39
39
|
|
|
40
40
|
| Parameter | Type | Default | Description |
|
|
41
41
|
| --------------------- | -------------------- | --------------- | -------------------------------------------------------------------------------------------------------- |
|
|
42
|
-
| `modelName` | `string` | — | Model identifier: `"gpt-4o"`, `"claude-3-5-sonnet"`, `"gemini-1.5-pro"`,
|
|
43
|
-
| `config` | `object` | — | API keys (`openAIAPIKey`, `anthropicAPIKey`, `googleAPIKey
|
|
42
|
+
| `modelName` | `string` | — | Model identifier: `"gpt-4o"`, `"claude-3-5-sonnet"`, `"gemini-1.5-pro"`, etc. |
|
|
43
|
+
| `config` | `object` | — | API keys (`openAIAPIKey`, `anthropicAPIKey`, `googleAPIKey`), `temperature`, `agentic`, `recursionLimit`, `tavily`, `tavilyAPIKey` |
|
|
44
44
|
| `prompt` | `string \| object[]` | — | Plain string or array of `{ role, content }` message objects |
|
|
45
45
|
| `onProgressReport` | `function \| null` | `null` | Async callback receiving `{ message, progress }` updates |
|
|
46
46
|
| `minPercent` | `number` | `0` | Lower bound for progress percentage |
|
|
@@ -338,7 +338,7 @@ A model that cannot tell it received half a regulation will reason over the half
|
|
|
338
338
|
|
|
339
339
|
**Notes**
|
|
340
340
|
|
|
341
|
-
- Works with every supported provider
|
|
341
|
+
- Works with every supported provider.
|
|
342
342
|
- Credits come from each response's own `usage` block rather than an estimate, and are accumulated on `usageTracker.tokens.tavilyCredits`, costed from the `tavily-credit-costs` constant (USD per credit; falls back to Tavily's list price of `0.008`).
|
|
343
343
|
- URLs are collected on `usageTracker.webSearchSources`, deduplicated across the whole run — Tavily's terms require citing the original sources when its content is shown to end users.
|
|
344
344
|
- Per-URL failures are surfaced in the tool result instead of being dropped, so a fetch failure is not mistaken for an absence of content.
|
|
@@ -355,11 +355,10 @@ A model that cannot tell it received half a regulation will reason over the half
|
|
|
355
355
|
| OpenAI | `gpt-` | `gpt-4o`, `gpt-4o-mini` |
|
|
356
356
|
| Anthropic | `claude-` | `claude-3-5-sonnet`, `claude-3-opus` |
|
|
357
357
|
| Google | `gemini-` | `gemini-1.5-pro`, `gemini-2.0-flash` |
|
|
358
|
-
| DeepSeek | `deepseek-` | `deepseek-chat`, `deepseek-reasoner` |
|
|
359
|
-
| Kimi (Moonshot) | `kimi-`, `moonshot-` | `kimi-k2-0905-preview`, `moonshot-v1-8k` |
|
|
360
|
-
| GLM (Zhipu) | `glm-` | `glm-4.6`, `glm-4.5` |
|
|
361
358
|
|
|
362
|
-
|
|
359
|
+
Native structured output is configured per provider when a Zod `schema` is passed: `response_format` with a JSON schema for `gpt-*`, `output_config.format` for `claude-*`, and JSON mode plus `responseSchema` for `gemini-*`.
|
|
360
|
+
|
|
361
|
+
Output token limits are not configurable. Anthropic requires `max_tokens` on every request, so `claude-*` is pinned to `64000` with streaming always enabled; `gpt-*` and `gemini-*` are sent no limit and use each provider's own default, which is that model's maximum.
|
|
363
362
|
|
|
364
363
|
### Image Generation
|
|
365
364
|
|
|
@@ -379,11 +378,7 @@ The `config` object accepted by LangChain methods supports the following keys:
|
|
|
379
378
|
| `openAIAPIKey` | `string` | OpenAI API key |
|
|
380
379
|
| `anthropicAPIKey` | `string` | Anthropic API key |
|
|
381
380
|
| `googleAPIKey` | `string` | Google AI API key |
|
|
382
|
-
| `deepSeekAPIKey` | `string` | DeepSeek API key |
|
|
383
|
-
| `kimiAPIKey` | `string` | Kimi (Moonshot) API key |
|
|
384
|
-
| `glmAPIKey` | `string` | GLM (Zhipu) API key |
|
|
385
381
|
| `temperature` | `number` | Sampling temperature |
|
|
386
|
-
| `maxTokens` | `number` | Maximum output tokens (default: `16384` for Claude, `200000` for other providers). For Claude, values above `21333` automatically enable LangChain streaming to bypass the Anthropic SDK's 10-minute non-streaming guard. |
|
|
387
382
|
| `agentic` | `boolean` | Enable agentic mode in `runPromptWithModel` |
|
|
388
383
|
| `recursionLimit` | `number` | Max agent steps (default: `25`) |
|
|
389
384
|
| `tavilyAPIKey` | `string` | Tavily API key; required when `tavily` is set |
|
package/dist/cjs/langChain.d.ts
CHANGED
|
@@ -23,23 +23,22 @@ export type UsageTracker = {
|
|
|
23
23
|
/**
|
|
24
24
|
* Instantiates and returns the appropriate LangChain chat model based on the model
|
|
25
25
|
* name prefix. `claude-` maps to `ChatAnthropic`, `gemini-` maps to
|
|
26
|
-
* `ChatGoogleGenerativeAI`, and `gpt-` maps to `ChatOpenAI`.
|
|
27
|
-
* Kimi/Moonshot (`kimi-`, `moonshot-`), and GLM/Zhipu (`glm-`) models are routed
|
|
28
|
-
* through `ChatOpenAI` against each provider's OpenAI-compatible endpoint. When a Zod
|
|
26
|
+
* `ChatGoogleGenerativeAI`, and `gpt-` maps to `ChatOpenAI`. When a Zod
|
|
29
27
|
* `schema` is provided, native structured output is configured per provider: OpenAI
|
|
30
28
|
* via `response_format` with `json_schema`, Anthropic via `output_config.format`, and
|
|
31
29
|
* Gemini via JSON mode (`json: true`) plus `responseSchema`. In every case the model
|
|
32
30
|
* emits JSON as the message text, so the caller's parse/validate pipeline is unchanged.
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
31
|
+
* Throws a `BAD_REQUEST` error for unrecognised model names.
|
|
32
|
+
*
|
|
33
|
+
* Output token limits are not caller-configurable. Anthropic requires
|
|
34
|
+
* `max_tokens` on every request and @langchain/anthropic defaults it to 4096,
|
|
35
|
+
* so the Claude branch pins it explicitly; OpenAI and Gemini are sent no limit
|
|
36
|
+
* and fall back to each provider's own default, which is that model's maximum.
|
|
36
37
|
* @param modelName - The model identifier, e.g. `"gpt-4o"`, `"claude-3-5-sonnet"`,
|
|
37
|
-
* `"gemini-1.5-pro"
|
|
38
|
+
* `"gemini-1.5-pro"`
|
|
38
39
|
* @param config - Configuration object containing API keys (`openAIAPIKey`,
|
|
39
|
-
* `anthropicAPIKey`, `googleAPIKey
|
|
40
|
-
* optional `maxTokens`, and optional `temperature`
|
|
40
|
+
* `anthropicAPIKey`, `googleAPIKey`) and optional `temperature`
|
|
41
41
|
* @param schema - Optional Zod schema used to configure native structured JSON output
|
|
42
|
-
* for GPT / Claude / Gemini models; ignored for OpenAI-compatible providers
|
|
43
42
|
* @returns A configured LangChain chat model (or bound runnable) instance
|
|
44
43
|
*/
|
|
45
44
|
export declare const getLLMModel: (modelName: string, config: any, schema?: any) => any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"langChain.d.ts","sourceRoot":"","sources":["../../src/langChain.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"langChain.d.ts","sourceRoot":"","sources":["../../src/langChain.ts"],"names":[],"mappings":"AA6GA;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACvC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACtD,CAAC;AA0lBF;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,eAAO,MAAM,WAAW,GACtB,WAAW,MAAM,EACjB,QAAQ,GAAG,EACX,SAAQ,GAAU,KACjB,GAwHF,CAAC;;0CA3uB2C,GAAG,KAAG,IAAI;wBA8vB/C,MAAM,aACD,MAAM,gBACH,MAAM,SACb,GAAG,EAAE,kBACI,GAAG,UACX,GAAG,iBACG,YAAY,GAAG,IAAI,KAChC,GAAG;sBAoCG,GAAG,UACF,MAAM,UACN,GAAG,eACC,QAAQ,GAAG,IAAI,iBACb,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;oCAkYF,MAAM,UACT,GAAG,UACH,GAAG,oBACO,GAAG,eACT,MAAM,eACN,MAAM,wBACG,OAAO,WACpB,GAAG,cACA,MAAM,UACV,GAAG,EAAE,iBACE,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;sDA2tBF,MAAM,UACT,GAAG,UACH,MAAM,YACL,GAAG,iBACE,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;sDAmTF,MAAM,UACT,GAAG,UACH,MAAM,YACL,GAAG,iBACE,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;0CA7zC8B,GAAG,KAAG,MAAM;+CA1uB9C,YAAY,GAAG,IAAI,GAAG,SAAS,aAC7B,MAAM,kBACD,MAAM,UACd,GAAG,KACV,IAAI;mCA0vBU,MAAM,mBACJ,MAAM,EAAE,KACxB,MAAM;;AAg2CT,wBAUE"}
|
package/dist/cjs/langChain.js
CHANGED
|
@@ -30,9 +30,10 @@ Do NOT include raw newlines, tabs, or unescaped quotes inside JSON string values
|
|
|
30
30
|
* Providers for which `getLLMModel` configures native, schema-constrained JSON
|
|
31
31
|
* output (OpenAI `response_format`, Anthropic `output_config.format`, Gemini
|
|
32
32
|
* `responseSchema` + JSON mode). For these the model emits JSON directly, so the
|
|
33
|
-
* prompt-injected schema and the schema-validation retry are skipped.
|
|
34
|
-
*
|
|
35
|
-
* support
|
|
33
|
+
* prompt-injected schema and the schema-validation retry are skipped. Every
|
|
34
|
+
* supported provider is listed here; the check remains so that adding one
|
|
35
|
+
* without native support falls back to prompt instructions + validation
|
|
36
|
+
* rather than silently skipping them.
|
|
36
37
|
* @param modelName - The model identifier being routed
|
|
37
38
|
* @returns `true` when native structured output is wired up for the provider
|
|
38
39
|
*/
|
|
@@ -543,36 +544,6 @@ const extractJSONFromResponse = (text) => {
|
|
|
543
544
|
}
|
|
544
545
|
return null;
|
|
545
546
|
};
|
|
546
|
-
/**
|
|
547
|
-
* Maps a model name prefix to its OpenAI-compatible provider configuration. DeepSeek,
|
|
548
|
-
* Kimi (Moonshot), and GLM (Zhipu) all expose OpenAI-compatible chat completion APIs
|
|
549
|
-
* and can be routed through `ChatOpenAI` with a custom base URL and API key.
|
|
550
|
-
* @param modelName - The model identifier to inspect
|
|
551
|
-
* @param config - Configuration object containing provider-specific API keys
|
|
552
|
-
* @returns An object with `apiKey` and `baseURL` when the model matches a known
|
|
553
|
-
* OpenAI-compatible provider, or `null` otherwise
|
|
554
|
-
*/
|
|
555
|
-
const getOpenAICompatibleProvider = (modelName, config) => {
|
|
556
|
-
if (modelName.startsWith("deepseek-")) {
|
|
557
|
-
return {
|
|
558
|
-
apiKey: config.deepSeekAPIKey,
|
|
559
|
-
baseURL: "https://api.deepseek.com/v1",
|
|
560
|
-
};
|
|
561
|
-
}
|
|
562
|
-
if (modelName.startsWith("kimi-") || modelName.startsWith("moonshot-")) {
|
|
563
|
-
return {
|
|
564
|
-
apiKey: config.kimiAPIKey,
|
|
565
|
-
baseURL: "https://api.moonshot.ai/v1",
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
if (modelName.startsWith("glm-")) {
|
|
569
|
-
return {
|
|
570
|
-
apiKey: config.glmAPIKey,
|
|
571
|
-
baseURL: "https://open.bigmodel.cn/api/paas/v4/",
|
|
572
|
-
};
|
|
573
|
-
}
|
|
574
|
-
return null;
|
|
575
|
-
};
|
|
576
547
|
/**
|
|
577
548
|
* Whether a model accepts the `temperature` sampling parameter at all. Some
|
|
578
549
|
* models reject it with an HTTP 400, so it must be omitted rather than clamped:
|
|
@@ -582,7 +553,7 @@ const getOpenAICompatibleProvider = (modelName, config) => {
|
|
|
582
553
|
* accept it.
|
|
583
554
|
* - OpenAI reasoning models (the GPT-5 family and the o-series) reject it;
|
|
584
555
|
* gpt-4o still accepts it.
|
|
585
|
-
*
|
|
556
|
+
* Gemini accepts temperature.
|
|
586
557
|
* @param modelName - the model identifier being routed
|
|
587
558
|
* @returns `true` when the model accepts a `temperature` parameter
|
|
588
559
|
*/
|
|
@@ -603,18 +574,14 @@ const modelSupportsTemperature = (modelName) => {
|
|
|
603
574
|
};
|
|
604
575
|
/**
|
|
605
576
|
* Per-provider valid `temperature` range, used to clamp caller-supplied values.
|
|
606
|
-
* Anthropic
|
|
607
|
-
*
|
|
608
|
-
* at all (see `modelSupportsTemperature`).
|
|
577
|
+
* Anthropic caps at 1.0; OpenAI and Gemini accept up to 2.0. Only consulted for
|
|
578
|
+
* models that support temperature at all (see `modelSupportsTemperature`).
|
|
609
579
|
*/
|
|
610
580
|
const getTemperatureRange = (modelName) => {
|
|
611
|
-
if (modelName.startsWith("claude-")
|
|
612
|
-
modelName.startsWith("kimi-") ||
|
|
613
|
-
modelName.startsWith("moonshot-") ||
|
|
614
|
-
modelName.startsWith("glm-")) {
|
|
581
|
+
if (modelName.startsWith("claude-")) {
|
|
615
582
|
return { min: 0, max: 1 };
|
|
616
583
|
}
|
|
617
|
-
// gpt-, gemini
|
|
584
|
+
// gpt-, gemini-
|
|
618
585
|
return { min: 0, max: 2 };
|
|
619
586
|
};
|
|
620
587
|
/**
|
|
@@ -670,23 +637,22 @@ const extractTextContent = (content) => {
|
|
|
670
637
|
/**
|
|
671
638
|
* Instantiates and returns the appropriate LangChain chat model based on the model
|
|
672
639
|
* name prefix. `claude-` maps to `ChatAnthropic`, `gemini-` maps to
|
|
673
|
-
* `ChatGoogleGenerativeAI`, and `gpt-` maps to `ChatOpenAI`.
|
|
674
|
-
* Kimi/Moonshot (`kimi-`, `moonshot-`), and GLM/Zhipu (`glm-`) models are routed
|
|
675
|
-
* through `ChatOpenAI` against each provider's OpenAI-compatible endpoint. When a Zod
|
|
640
|
+
* `ChatGoogleGenerativeAI`, and `gpt-` maps to `ChatOpenAI`. When a Zod
|
|
676
641
|
* `schema` is provided, native structured output is configured per provider: OpenAI
|
|
677
642
|
* via `response_format` with `json_schema`, Anthropic via `output_config.format`, and
|
|
678
643
|
* Gemini via JSON mode (`json: true`) plus `responseSchema`. In every case the model
|
|
679
644
|
* emits JSON as the message text, so the caller's parse/validate pipeline is unchanged.
|
|
680
|
-
*
|
|
681
|
-
*
|
|
682
|
-
*
|
|
645
|
+
* Throws a `BAD_REQUEST` error for unrecognised model names.
|
|
646
|
+
*
|
|
647
|
+
* Output token limits are not caller-configurable. Anthropic requires
|
|
648
|
+
* `max_tokens` on every request and @langchain/anthropic defaults it to 4096,
|
|
649
|
+
* so the Claude branch pins it explicitly; OpenAI and Gemini are sent no limit
|
|
650
|
+
* and fall back to each provider's own default, which is that model's maximum.
|
|
683
651
|
* @param modelName - The model identifier, e.g. `"gpt-4o"`, `"claude-3-5-sonnet"`,
|
|
684
|
-
* `"gemini-1.5-pro"
|
|
652
|
+
* `"gemini-1.5-pro"`
|
|
685
653
|
* @param config - Configuration object containing API keys (`openAIAPIKey`,
|
|
686
|
-
* `anthropicAPIKey`, `googleAPIKey
|
|
687
|
-
* optional `maxTokens`, and optional `temperature`
|
|
654
|
+
* `anthropicAPIKey`, `googleAPIKey`) and optional `temperature`
|
|
688
655
|
* @param schema - Optional Zod schema used to configure native structured JSON output
|
|
689
|
-
* for GPT / Claude / Gemini models; ignored for OpenAI-compatible providers
|
|
690
656
|
* @returns A configured LangChain chat model (or bound runnable) instance
|
|
691
657
|
*/
|
|
692
658
|
// Exported (but not re-exported from index.ts / the package's public entry
|
|
@@ -697,12 +663,17 @@ const getLLMModel = (modelName, config, schema = null) => {
|
|
|
697
663
|
const modelSettings = resolveTemperatureSetting(modelName, config);
|
|
698
664
|
// Claude models (Anthropic)
|
|
699
665
|
if (modelName.startsWith("claude-")) {
|
|
666
|
+
// Anthropic requires `max_tokens` on every request and @langchain/anthropic
|
|
667
|
+
// defaults it to 4096 when omitted — low enough to truncate agentic turns
|
|
668
|
+
// mid-tool-call — so it is pinned here rather than left to the library.
|
|
669
|
+
// 64000 is Anthropic's recommended value for streamed requests and sits
|
|
670
|
+
// within the 128000-token output limit of every Claude model routed here.
|
|
671
|
+
//
|
|
700
672
|
// Anthropic's SDK rejects non-streamed requests when max_tokens is large
|
|
701
|
-
// enough that the operation could exceed 10 minutes (threshold: 21333)
|
|
702
|
-
//
|
|
703
|
-
//
|
|
704
|
-
|
|
705
|
-
const maxTokens = config.maxTokens || 16384;
|
|
673
|
+
// enough that the operation could exceed 10 minutes (threshold: 21333), so
|
|
674
|
+
// streaming is always on: `.invoke()` routes through the streaming endpoint
|
|
675
|
+
// internally and callers see no interface change.
|
|
676
|
+
const maxTokens = 64000;
|
|
706
677
|
// Native structured output: Anthropic's `output_config.format` constrains
|
|
707
678
|
// decoding to the schema while still emitting JSON as the message text, so
|
|
708
679
|
// the downstream streaming + parse/validate pipeline is unchanged.
|
|
@@ -723,7 +694,7 @@ const getLLMModel = (modelName, config, schema = null) => {
|
|
|
723
694
|
apiKey: config.anthropicAPIKey,
|
|
724
695
|
maxTokens,
|
|
725
696
|
modelName: modelName,
|
|
726
|
-
streaming:
|
|
697
|
+
streaming: true,
|
|
727
698
|
invocationKwargs: { cache_control: { type: "ephemeral" } },
|
|
728
699
|
...outputConfig,
|
|
729
700
|
...modelSettings,
|
|
@@ -734,7 +705,9 @@ const getLLMModel = (modelName, config, schema = null) => {
|
|
|
734
705
|
else if (modelName.startsWith("gemini-")) {
|
|
735
706
|
const model = new google_genai_1.ChatGoogleGenerativeAI({
|
|
736
707
|
apiKey: config.googleAPIKey,
|
|
737
|
-
maxOutputTokens
|
|
708
|
+
// No `maxOutputTokens`: omitting it leaves Gemini's own default, which is
|
|
709
|
+
// the model's maximum output. Sending a value meant tracking a per-model
|
|
710
|
+
// ceiling that the API rejects outright rather than clamps.
|
|
738
711
|
model: modelName,
|
|
739
712
|
// `json: true` forces responseMimeType=application/json, guaranteeing the
|
|
740
713
|
// model returns valid JSON text (never prose) for the parse pipeline.
|
|
@@ -756,17 +729,26 @@ const getLLMModel = (modelName, config, schema = null) => {
|
|
|
756
729
|
else if (modelName.startsWith("gpt-")) {
|
|
757
730
|
const openAISettings = {
|
|
758
731
|
apiKey: config.openAIAPIKey,
|
|
759
|
-
|
|
732
|
+
// No output limit is sent: OpenAI defaults to the model's maximum. The
|
|
733
|
+
// snake_case `max_tokens` that used to sit here was never a recognised
|
|
734
|
+
// ChatOpenAI field and was silently dropped by LangChain.
|
|
760
735
|
modelName: modelName,
|
|
761
736
|
...modelSettings,
|
|
762
737
|
};
|
|
763
|
-
// gpt-5.6's /v1/chat/completions endpoint 400s whenever function
|
|
764
|
-
// bound, because it rejects the model's own server-side default
|
|
765
|
-
// effort in that combination ("use /v1/responses or set
|
|
766
|
-
// to 'none'"); forcing it to "none" here avoids the
|
|
767
|
-
//
|
|
768
|
-
//
|
|
769
|
-
|
|
738
|
+
// The gpt-5.6 family's /v1/chat/completions endpoint 400s whenever function
|
|
739
|
+
// tools are bound, because it rejects the model's own server-side default
|
|
740
|
+
// reasoning effort in that combination ("use /v1/responses or set
|
|
741
|
+
// reasoning_effort to 'none'"); forcing it to "none" here avoids the
|
|
742
|
+
// collision. The restriction belongs to the family, not to one id: the
|
|
743
|
+
// `gpt-5.6` alias resolves to `gpt-5.6-sol`, and `gpt-5.6-terra` /
|
|
744
|
+
// `gpt-5.6-luna` are separately addressable ids that hit the same 400, as
|
|
745
|
+
// do dated snapshots (`gpt-5.6-2026-08-22`). Matching the alias alone left
|
|
746
|
+
// every one of those unpatched, so match the whole family. Still excludes
|
|
747
|
+
// sibling releases (gpt-5.5, gpt-5.7): they are not confirmed to share the
|
|
748
|
+
// bug, and reasoning effort is worth keeping wherever it is accepted.
|
|
749
|
+
const reasoningEffortOverride = /^gpt-5\.6($|-)/.test(modelName)
|
|
750
|
+
? { reasoning_effort: "none" }
|
|
751
|
+
: {};
|
|
770
752
|
// Use native structured output with a JSON schema. `modelKwargs` is spread
|
|
771
753
|
// verbatim into the Chat Completions request. Merge (not overwrite) with
|
|
772
754
|
// the reasoning-effort override above, since both may apply at once.
|
|
@@ -789,17 +771,6 @@ const getLLMModel = (modelName, config, schema = null) => {
|
|
|
789
771
|
}
|
|
790
772
|
return new openai_1.ChatOpenAI(openAISettings);
|
|
791
773
|
}
|
|
792
|
-
// OpenAI-compatible providers: DeepSeek, Kimi (Moonshot), GLM (Zhipu)
|
|
793
|
-
const openAICompatible = getOpenAICompatibleProvider(modelName, config);
|
|
794
|
-
if (openAICompatible) {
|
|
795
|
-
return new openai_1.ChatOpenAI({
|
|
796
|
-
apiKey: openAICompatible.apiKey,
|
|
797
|
-
maxTokens: config.maxTokens || 200000,
|
|
798
|
-
modelName: modelName,
|
|
799
|
-
configuration: { baseURL: openAICompatible.baseURL },
|
|
800
|
-
...modelSettings,
|
|
801
|
-
});
|
|
802
|
-
}
|
|
803
774
|
throw errorHandling_js_1.default.create(const_js_1.default.HTTP_CODES.BAD_REQUEST, const_js_1.default.ERROR.UNSUPPORTED_MODEL + ": " + modelName);
|
|
804
775
|
};
|
|
805
776
|
exports.getLLMModel = getLLMModel;
|
package/dist/esm/langChain.d.ts
CHANGED
|
@@ -23,23 +23,22 @@ export type UsageTracker = {
|
|
|
23
23
|
/**
|
|
24
24
|
* Instantiates and returns the appropriate LangChain chat model based on the model
|
|
25
25
|
* name prefix. `claude-` maps to `ChatAnthropic`, `gemini-` maps to
|
|
26
|
-
* `ChatGoogleGenerativeAI`, and `gpt-` maps to `ChatOpenAI`.
|
|
27
|
-
* Kimi/Moonshot (`kimi-`, `moonshot-`), and GLM/Zhipu (`glm-`) models are routed
|
|
28
|
-
* through `ChatOpenAI` against each provider's OpenAI-compatible endpoint. When a Zod
|
|
26
|
+
* `ChatGoogleGenerativeAI`, and `gpt-` maps to `ChatOpenAI`. When a Zod
|
|
29
27
|
* `schema` is provided, native structured output is configured per provider: OpenAI
|
|
30
28
|
* via `response_format` with `json_schema`, Anthropic via `output_config.format`, and
|
|
31
29
|
* Gemini via JSON mode (`json: true`) plus `responseSchema`. In every case the model
|
|
32
30
|
* emits JSON as the message text, so the caller's parse/validate pipeline is unchanged.
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
31
|
+
* Throws a `BAD_REQUEST` error for unrecognised model names.
|
|
32
|
+
*
|
|
33
|
+
* Output token limits are not caller-configurable. Anthropic requires
|
|
34
|
+
* `max_tokens` on every request and @langchain/anthropic defaults it to 4096,
|
|
35
|
+
* so the Claude branch pins it explicitly; OpenAI and Gemini are sent no limit
|
|
36
|
+
* and fall back to each provider's own default, which is that model's maximum.
|
|
36
37
|
* @param modelName - The model identifier, e.g. `"gpt-4o"`, `"claude-3-5-sonnet"`,
|
|
37
|
-
* `"gemini-1.5-pro"
|
|
38
|
+
* `"gemini-1.5-pro"`
|
|
38
39
|
* @param config - Configuration object containing API keys (`openAIAPIKey`,
|
|
39
|
-
* `anthropicAPIKey`, `googleAPIKey
|
|
40
|
-
* optional `maxTokens`, and optional `temperature`
|
|
40
|
+
* `anthropicAPIKey`, `googleAPIKey`) and optional `temperature`
|
|
41
41
|
* @param schema - Optional Zod schema used to configure native structured JSON output
|
|
42
|
-
* for GPT / Claude / Gemini models; ignored for OpenAI-compatible providers
|
|
43
42
|
* @returns A configured LangChain chat model (or bound runnable) instance
|
|
44
43
|
*/
|
|
45
44
|
export declare const getLLMModel: (modelName: string, config: any, schema?: any) => any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"langChain.d.ts","sourceRoot":"","sources":["../../src/langChain.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"langChain.d.ts","sourceRoot":"","sources":["../../src/langChain.ts"],"names":[],"mappings":"AA6GA;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACvC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACtD,CAAC;AA0lBF;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,eAAO,MAAM,WAAW,GACtB,WAAW,MAAM,EACjB,QAAQ,GAAG,EACX,SAAQ,GAAU,KACjB,GAwHF,CAAC;;0CA3uB2C,GAAG,KAAG,IAAI;wBA8vB/C,MAAM,aACD,MAAM,gBACH,MAAM,SACb,GAAG,EAAE,kBACI,GAAG,UACX,GAAG,iBACG,YAAY,GAAG,IAAI,KAChC,GAAG;sBAoCG,GAAG,UACF,MAAM,UACN,GAAG,eACC,QAAQ,GAAG,IAAI,iBACb,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;oCAkYF,MAAM,UACT,GAAG,UACH,GAAG,oBACO,GAAG,eACT,MAAM,eACN,MAAM,wBACG,OAAO,WACpB,GAAG,cACA,MAAM,UACV,GAAG,EAAE,iBACE,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;sDA2tBF,MAAM,UACT,GAAG,UACH,MAAM,YACL,GAAG,iBACE,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;sDAmTF,MAAM,UACT,GAAG,UACH,MAAM,YACL,GAAG,iBACE,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;0CA7zC8B,GAAG,KAAG,MAAM;+CA1uB9C,YAAY,GAAG,IAAI,GAAG,SAAS,aAC7B,MAAM,kBACD,MAAM,UACd,GAAG,KACV,IAAI;mCA0vBU,MAAM,mBACJ,MAAM,EAAE,KACxB,MAAM;;AAg2CT,wBAUE"}
|
package/dist/esm/langChain.js
CHANGED
|
@@ -24,9 +24,10 @@ Do NOT include raw newlines, tabs, or unescaped quotes inside JSON string values
|
|
|
24
24
|
* Providers for which `getLLMModel` configures native, schema-constrained JSON
|
|
25
25
|
* output (OpenAI `response_format`, Anthropic `output_config.format`, Gemini
|
|
26
26
|
* `responseSchema` + JSON mode). For these the model emits JSON directly, so the
|
|
27
|
-
* prompt-injected schema and the schema-validation retry are skipped.
|
|
28
|
-
*
|
|
29
|
-
* support
|
|
27
|
+
* prompt-injected schema and the schema-validation retry are skipped. Every
|
|
28
|
+
* supported provider is listed here; the check remains so that adding one
|
|
29
|
+
* without native support falls back to prompt instructions + validation
|
|
30
|
+
* rather than silently skipping them.
|
|
30
31
|
* @param modelName - The model identifier being routed
|
|
31
32
|
* @returns `true` when native structured output is wired up for the provider
|
|
32
33
|
*/
|
|
@@ -537,36 +538,6 @@ const extractJSONFromResponse = (text) => {
|
|
|
537
538
|
}
|
|
538
539
|
return null;
|
|
539
540
|
};
|
|
540
|
-
/**
|
|
541
|
-
* Maps a model name prefix to its OpenAI-compatible provider configuration. DeepSeek,
|
|
542
|
-
* Kimi (Moonshot), and GLM (Zhipu) all expose OpenAI-compatible chat completion APIs
|
|
543
|
-
* and can be routed through `ChatOpenAI` with a custom base URL and API key.
|
|
544
|
-
* @param modelName - The model identifier to inspect
|
|
545
|
-
* @param config - Configuration object containing provider-specific API keys
|
|
546
|
-
* @returns An object with `apiKey` and `baseURL` when the model matches a known
|
|
547
|
-
* OpenAI-compatible provider, or `null` otherwise
|
|
548
|
-
*/
|
|
549
|
-
const getOpenAICompatibleProvider = (modelName, config) => {
|
|
550
|
-
if (modelName.startsWith("deepseek-")) {
|
|
551
|
-
return {
|
|
552
|
-
apiKey: config.deepSeekAPIKey,
|
|
553
|
-
baseURL: "https://api.deepseek.com/v1",
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
|
-
if (modelName.startsWith("kimi-") || modelName.startsWith("moonshot-")) {
|
|
557
|
-
return {
|
|
558
|
-
apiKey: config.kimiAPIKey,
|
|
559
|
-
baseURL: "https://api.moonshot.ai/v1",
|
|
560
|
-
};
|
|
561
|
-
}
|
|
562
|
-
if (modelName.startsWith("glm-")) {
|
|
563
|
-
return {
|
|
564
|
-
apiKey: config.glmAPIKey,
|
|
565
|
-
baseURL: "https://open.bigmodel.cn/api/paas/v4/",
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
return null;
|
|
569
|
-
};
|
|
570
541
|
/**
|
|
571
542
|
* Whether a model accepts the `temperature` sampling parameter at all. Some
|
|
572
543
|
* models reject it with an HTTP 400, so it must be omitted rather than clamped:
|
|
@@ -576,7 +547,7 @@ const getOpenAICompatibleProvider = (modelName, config) => {
|
|
|
576
547
|
* accept it.
|
|
577
548
|
* - OpenAI reasoning models (the GPT-5 family and the o-series) reject it;
|
|
578
549
|
* gpt-4o still accepts it.
|
|
579
|
-
*
|
|
550
|
+
* Gemini accepts temperature.
|
|
580
551
|
* @param modelName - the model identifier being routed
|
|
581
552
|
* @returns `true` when the model accepts a `temperature` parameter
|
|
582
553
|
*/
|
|
@@ -597,18 +568,14 @@ const modelSupportsTemperature = (modelName) => {
|
|
|
597
568
|
};
|
|
598
569
|
/**
|
|
599
570
|
* Per-provider valid `temperature` range, used to clamp caller-supplied values.
|
|
600
|
-
* Anthropic
|
|
601
|
-
*
|
|
602
|
-
* at all (see `modelSupportsTemperature`).
|
|
571
|
+
* Anthropic caps at 1.0; OpenAI and Gemini accept up to 2.0. Only consulted for
|
|
572
|
+
* models that support temperature at all (see `modelSupportsTemperature`).
|
|
603
573
|
*/
|
|
604
574
|
const getTemperatureRange = (modelName) => {
|
|
605
|
-
if (modelName.startsWith("claude-")
|
|
606
|
-
modelName.startsWith("kimi-") ||
|
|
607
|
-
modelName.startsWith("moonshot-") ||
|
|
608
|
-
modelName.startsWith("glm-")) {
|
|
575
|
+
if (modelName.startsWith("claude-")) {
|
|
609
576
|
return { min: 0, max: 1 };
|
|
610
577
|
}
|
|
611
|
-
// gpt-, gemini
|
|
578
|
+
// gpt-, gemini-
|
|
612
579
|
return { min: 0, max: 2 };
|
|
613
580
|
};
|
|
614
581
|
/**
|
|
@@ -664,23 +631,22 @@ const extractTextContent = (content) => {
|
|
|
664
631
|
/**
|
|
665
632
|
* Instantiates and returns the appropriate LangChain chat model based on the model
|
|
666
633
|
* name prefix. `claude-` maps to `ChatAnthropic`, `gemini-` maps to
|
|
667
|
-
* `ChatGoogleGenerativeAI`, and `gpt-` maps to `ChatOpenAI`.
|
|
668
|
-
* Kimi/Moonshot (`kimi-`, `moonshot-`), and GLM/Zhipu (`glm-`) models are routed
|
|
669
|
-
* through `ChatOpenAI` against each provider's OpenAI-compatible endpoint. When a Zod
|
|
634
|
+
* `ChatGoogleGenerativeAI`, and `gpt-` maps to `ChatOpenAI`. When a Zod
|
|
670
635
|
* `schema` is provided, native structured output is configured per provider: OpenAI
|
|
671
636
|
* via `response_format` with `json_schema`, Anthropic via `output_config.format`, and
|
|
672
637
|
* Gemini via JSON mode (`json: true`) plus `responseSchema`. In every case the model
|
|
673
638
|
* emits JSON as the message text, so the caller's parse/validate pipeline is unchanged.
|
|
674
|
-
*
|
|
675
|
-
*
|
|
676
|
-
*
|
|
639
|
+
* Throws a `BAD_REQUEST` error for unrecognised model names.
|
|
640
|
+
*
|
|
641
|
+
* Output token limits are not caller-configurable. Anthropic requires
|
|
642
|
+
* `max_tokens` on every request and @langchain/anthropic defaults it to 4096,
|
|
643
|
+
* so the Claude branch pins it explicitly; OpenAI and Gemini are sent no limit
|
|
644
|
+
* and fall back to each provider's own default, which is that model's maximum.
|
|
677
645
|
* @param modelName - The model identifier, e.g. `"gpt-4o"`, `"claude-3-5-sonnet"`,
|
|
678
|
-
* `"gemini-1.5-pro"
|
|
646
|
+
* `"gemini-1.5-pro"`
|
|
679
647
|
* @param config - Configuration object containing API keys (`openAIAPIKey`,
|
|
680
|
-
* `anthropicAPIKey`, `googleAPIKey
|
|
681
|
-
* optional `maxTokens`, and optional `temperature`
|
|
648
|
+
* `anthropicAPIKey`, `googleAPIKey`) and optional `temperature`
|
|
682
649
|
* @param schema - Optional Zod schema used to configure native structured JSON output
|
|
683
|
-
* for GPT / Claude / Gemini models; ignored for OpenAI-compatible providers
|
|
684
650
|
* @returns A configured LangChain chat model (or bound runnable) instance
|
|
685
651
|
*/
|
|
686
652
|
// Exported (but not re-exported from index.ts / the package's public entry
|
|
@@ -691,12 +657,17 @@ export const getLLMModel = (modelName, config, schema = null) => {
|
|
|
691
657
|
const modelSettings = resolveTemperatureSetting(modelName, config);
|
|
692
658
|
// Claude models (Anthropic)
|
|
693
659
|
if (modelName.startsWith("claude-")) {
|
|
660
|
+
// Anthropic requires `max_tokens` on every request and @langchain/anthropic
|
|
661
|
+
// defaults it to 4096 when omitted — low enough to truncate agentic turns
|
|
662
|
+
// mid-tool-call — so it is pinned here rather than left to the library.
|
|
663
|
+
// 64000 is Anthropic's recommended value for streamed requests and sits
|
|
664
|
+
// within the 128000-token output limit of every Claude model routed here.
|
|
665
|
+
//
|
|
694
666
|
// Anthropic's SDK rejects non-streamed requests when max_tokens is large
|
|
695
|
-
// enough that the operation could exceed 10 minutes (threshold: 21333)
|
|
696
|
-
//
|
|
697
|
-
//
|
|
698
|
-
|
|
699
|
-
const maxTokens = config.maxTokens || 16384;
|
|
667
|
+
// enough that the operation could exceed 10 minutes (threshold: 21333), so
|
|
668
|
+
// streaming is always on: `.invoke()` routes through the streaming endpoint
|
|
669
|
+
// internally and callers see no interface change.
|
|
670
|
+
const maxTokens = 64000;
|
|
700
671
|
// Native structured output: Anthropic's `output_config.format` constrains
|
|
701
672
|
// decoding to the schema while still emitting JSON as the message text, so
|
|
702
673
|
// the downstream streaming + parse/validate pipeline is unchanged.
|
|
@@ -717,7 +688,7 @@ export const getLLMModel = (modelName, config, schema = null) => {
|
|
|
717
688
|
apiKey: config.anthropicAPIKey,
|
|
718
689
|
maxTokens,
|
|
719
690
|
modelName: modelName,
|
|
720
|
-
streaming:
|
|
691
|
+
streaming: true,
|
|
721
692
|
invocationKwargs: { cache_control: { type: "ephemeral" } },
|
|
722
693
|
...outputConfig,
|
|
723
694
|
...modelSettings,
|
|
@@ -728,7 +699,9 @@ export const getLLMModel = (modelName, config, schema = null) => {
|
|
|
728
699
|
else if (modelName.startsWith("gemini-")) {
|
|
729
700
|
const model = new ChatGoogleGenerativeAI({
|
|
730
701
|
apiKey: config.googleAPIKey,
|
|
731
|
-
maxOutputTokens
|
|
702
|
+
// No `maxOutputTokens`: omitting it leaves Gemini's own default, which is
|
|
703
|
+
// the model's maximum output. Sending a value meant tracking a per-model
|
|
704
|
+
// ceiling that the API rejects outright rather than clamps.
|
|
732
705
|
model: modelName,
|
|
733
706
|
// `json: true` forces responseMimeType=application/json, guaranteeing the
|
|
734
707
|
// model returns valid JSON text (never prose) for the parse pipeline.
|
|
@@ -750,17 +723,26 @@ export const getLLMModel = (modelName, config, schema = null) => {
|
|
|
750
723
|
else if (modelName.startsWith("gpt-")) {
|
|
751
724
|
const openAISettings = {
|
|
752
725
|
apiKey: config.openAIAPIKey,
|
|
753
|
-
|
|
726
|
+
// No output limit is sent: OpenAI defaults to the model's maximum. The
|
|
727
|
+
// snake_case `max_tokens` that used to sit here was never a recognised
|
|
728
|
+
// ChatOpenAI field and was silently dropped by LangChain.
|
|
754
729
|
modelName: modelName,
|
|
755
730
|
...modelSettings,
|
|
756
731
|
};
|
|
757
|
-
// gpt-5.6's /v1/chat/completions endpoint 400s whenever function
|
|
758
|
-
// bound, because it rejects the model's own server-side default
|
|
759
|
-
// effort in that combination ("use /v1/responses or set
|
|
760
|
-
// to 'none'"); forcing it to "none" here avoids the
|
|
761
|
-
//
|
|
762
|
-
//
|
|
763
|
-
|
|
732
|
+
// The gpt-5.6 family's /v1/chat/completions endpoint 400s whenever function
|
|
733
|
+
// tools are bound, because it rejects the model's own server-side default
|
|
734
|
+
// reasoning effort in that combination ("use /v1/responses or set
|
|
735
|
+
// reasoning_effort to 'none'"); forcing it to "none" here avoids the
|
|
736
|
+
// collision. The restriction belongs to the family, not to one id: the
|
|
737
|
+
// `gpt-5.6` alias resolves to `gpt-5.6-sol`, and `gpt-5.6-terra` /
|
|
738
|
+
// `gpt-5.6-luna` are separately addressable ids that hit the same 400, as
|
|
739
|
+
// do dated snapshots (`gpt-5.6-2026-08-22`). Matching the alias alone left
|
|
740
|
+
// every one of those unpatched, so match the whole family. Still excludes
|
|
741
|
+
// sibling releases (gpt-5.5, gpt-5.7): they are not confirmed to share the
|
|
742
|
+
// bug, and reasoning effort is worth keeping wherever it is accepted.
|
|
743
|
+
const reasoningEffortOverride = /^gpt-5\.6($|-)/.test(modelName)
|
|
744
|
+
? { reasoning_effort: "none" }
|
|
745
|
+
: {};
|
|
764
746
|
// Use native structured output with a JSON schema. `modelKwargs` is spread
|
|
765
747
|
// verbatim into the Chat Completions request. Merge (not overwrite) with
|
|
766
748
|
// the reasoning-effort override above, since both may apply at once.
|
|
@@ -783,17 +765,6 @@ export const getLLMModel = (modelName, config, schema = null) => {
|
|
|
783
765
|
}
|
|
784
766
|
return new ChatOpenAI(openAISettings);
|
|
785
767
|
}
|
|
786
|
-
// OpenAI-compatible providers: DeepSeek, Kimi (Moonshot), GLM (Zhipu)
|
|
787
|
-
const openAICompatible = getOpenAICompatibleProvider(modelName, config);
|
|
788
|
-
if (openAICompatible) {
|
|
789
|
-
return new ChatOpenAI({
|
|
790
|
-
apiKey: openAICompatible.apiKey,
|
|
791
|
-
maxTokens: config.maxTokens || 200000,
|
|
792
|
-
modelName: modelName,
|
|
793
|
-
configuration: { baseURL: openAICompatible.baseURL },
|
|
794
|
-
...modelSettings,
|
|
795
|
-
});
|
|
796
|
-
}
|
|
797
768
|
throw errorHandlingHelper.create(constants.HTTP_CODES.BAD_REQUEST, constants.ERROR.UNSUPPORTED_MODEL + ": " + modelName);
|
|
798
769
|
};
|
|
799
770
|
/**
|