@flutchai/flutch-sdk 0.6.3 → 0.6.6
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/dist/index.cjs +396 -78
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +108 -37
- package/dist/index.d.ts +108 -37
- package/dist/index.js +384 -79
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1908,13 +1908,13 @@ async function findAvailablePort(startPort) {
|
|
|
1908
1908
|
throw new Error(`No available ports found in range ${startPort}-${startPort + 99}`);
|
|
1909
1909
|
}
|
|
1910
1910
|
__name(findAvailablePort, "findAvailablePort");
|
|
1911
|
-
async function registerWithServiceDiscovery(AppModule, port,
|
|
1911
|
+
async function registerWithServiceDiscovery(AppModule, port, logger3, app) {
|
|
1912
1912
|
try {
|
|
1913
|
-
|
|
1913
|
+
logger3.debug("[SERVICE_DISCOVERY] Starting service discovery registration...");
|
|
1914
1914
|
const { FileBasedDiscovery: FileBasedDiscovery2 } = await Promise.resolve().then(() => (init_file_based_discovery(), file_based_discovery_exports));
|
|
1915
|
-
|
|
1915
|
+
logger3.debug("[SERVICE_DISCOVERY] FileBasedDiscovery imported successfully");
|
|
1916
1916
|
const discovery = new FileBasedDiscovery2();
|
|
1917
|
-
|
|
1917
|
+
logger3.debug("[SERVICE_DISCOVERY] FileBasedDiscovery instance created");
|
|
1918
1918
|
const serviceName = AppModule.name.replace("Module", "").toLowerCase();
|
|
1919
1919
|
let graphTypes = [];
|
|
1920
1920
|
try {
|
|
@@ -1923,26 +1923,26 @@ async function registerWithServiceDiscovery(AppModule, port, logger2, app) {
|
|
|
1923
1923
|
const builderRegistry = app.get(BuilderRegistryService2, {
|
|
1924
1924
|
strict: false
|
|
1925
1925
|
});
|
|
1926
|
-
|
|
1926
|
+
logger3.debug(`BuilderRegistryService found in DI: ${!!builderRegistry}`);
|
|
1927
1927
|
if (builderRegistry) {
|
|
1928
1928
|
const builders = builderRegistry.getBuilders();
|
|
1929
|
-
|
|
1929
|
+
logger3.debug(`Found ${builders.length} builders in registry`);
|
|
1930
1930
|
const baseGraphTypes = builders.map((builder) => builder.graphType);
|
|
1931
|
-
|
|
1931
|
+
logger3.debug(`Base graph types: [${baseGraphTypes.join(", ")}]`);
|
|
1932
1932
|
try {
|
|
1933
|
-
|
|
1933
|
+
logger3.debug("Attempting to import VersionedGraphService...");
|
|
1934
1934
|
const { VersionedGraphService: VersionedGraphService2 } = await Promise.resolve().then(() => (init_versioned_graph_service(), versioned_graph_service_exports));
|
|
1935
|
-
|
|
1935
|
+
logger3.debug("VersionedGraphService imported successfully");
|
|
1936
1936
|
const versionedService = app.get(VersionedGraphService2, {
|
|
1937
1937
|
strict: false
|
|
1938
1938
|
});
|
|
1939
|
-
|
|
1939
|
+
logger3.debug(`VersionedGraphService found in DI: ${!!versionedService}`);
|
|
1940
1940
|
if (versionedService) {
|
|
1941
1941
|
const allVersionedTypes = [];
|
|
1942
1942
|
for (const baseType of baseGraphTypes) {
|
|
1943
|
-
|
|
1943
|
+
logger3.debug(`Getting versions for base type: ${baseType}`);
|
|
1944
1944
|
const versions = versionedService.getAvailableVersions(baseType);
|
|
1945
|
-
|
|
1945
|
+
logger3.debug(`Found ${versions.length} versions for ${baseType}: [${versions.join(", ")}]`);
|
|
1946
1946
|
if (versions.length > 0) {
|
|
1947
1947
|
allVersionedTypes.push(baseType);
|
|
1948
1948
|
versions.forEach((version) => {
|
|
@@ -1953,23 +1953,23 @@ async function registerWithServiceDiscovery(AppModule, port, logger2, app) {
|
|
|
1953
1953
|
}
|
|
1954
1954
|
}
|
|
1955
1955
|
graphTypes = allVersionedTypes;
|
|
1956
|
-
|
|
1956
|
+
logger3.debug(`Found ${baseGraphTypes.length} base types with ${graphTypes.length} total versioned types: ${graphTypes.join(", ")}`);
|
|
1957
1957
|
} else {
|
|
1958
1958
|
graphTypes = baseGraphTypes;
|
|
1959
|
-
|
|
1959
|
+
logger3.debug(`VersionedGraphService not found in DI container, using base types: ${graphTypes.join(", ")}`);
|
|
1960
1960
|
}
|
|
1961
1961
|
} catch (error) {
|
|
1962
1962
|
graphTypes = baseGraphTypes;
|
|
1963
|
-
|
|
1964
|
-
|
|
1963
|
+
logger3.debug(`Failed to get versioned types, using base types: ${error.message}`);
|
|
1964
|
+
logger3.debug(`Stack trace: ${error.stack}`);
|
|
1965
1965
|
}
|
|
1966
1966
|
}
|
|
1967
1967
|
}
|
|
1968
1968
|
} catch (error) {
|
|
1969
|
-
|
|
1969
|
+
logger3.debug(`Failed to get graph types from builders: ${error.message}`);
|
|
1970
1970
|
}
|
|
1971
1971
|
if (graphTypes.length === 0) {
|
|
1972
|
-
|
|
1972
|
+
logger3.debug("No builders found, using service name as graph type");
|
|
1973
1973
|
graphTypes = [
|
|
1974
1974
|
serviceName
|
|
1975
1975
|
];
|
|
@@ -1980,21 +1980,21 @@ async function registerWithServiceDiscovery(AppModule, port, logger2, app) {
|
|
|
1980
1980
|
startTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1981
1981
|
version: process.env.npm_package_version || "1.0.0"
|
|
1982
1982
|
}, graphTypes);
|
|
1983
|
-
|
|
1983
|
+
logger3.log(`\u{1F4E1} Service registered with discovery: ${serviceName} (types: ${graphTypes.join(", ")})`);
|
|
1984
1984
|
} catch (error) {
|
|
1985
|
-
|
|
1985
|
+
logger3.warn(`Failed to register with service discovery: ${error.message}`);
|
|
1986
1986
|
}
|
|
1987
1987
|
}
|
|
1988
1988
|
__name(registerWithServiceDiscovery, "registerWithServiceDiscovery");
|
|
1989
1989
|
async function bootstrap(AppModule, options = {}) {
|
|
1990
1990
|
setupRedisMock();
|
|
1991
1991
|
const app = await core.NestFactory.create(AppModule);
|
|
1992
|
-
const
|
|
1992
|
+
const logger3 = new common.Logger("Bootstrap");
|
|
1993
1993
|
const requestedPort = options.port || parseInt(process.env.PORT || "3100", 10);
|
|
1994
1994
|
const port = await findAvailablePort(requestedPort);
|
|
1995
1995
|
const globalPrefix = options.globalPrefix;
|
|
1996
1996
|
if (port !== requestedPort) {
|
|
1997
|
-
|
|
1997
|
+
logger3.warn(`Port ${requestedPort} is busy, using port ${port} instead`);
|
|
1998
1998
|
}
|
|
1999
1999
|
if (globalPrefix) {
|
|
2000
2000
|
app.setGlobalPrefix(globalPrefix);
|
|
@@ -2013,13 +2013,13 @@ async function bootstrap(AppModule, options = {}) {
|
|
|
2013
2013
|
swagger.SwaggerModule.setup("api/docs", app, document);
|
|
2014
2014
|
await app.listen(port);
|
|
2015
2015
|
const baseUrl = globalPrefix ? `http://localhost:${port}/${globalPrefix}` : `http://localhost:${port}`;
|
|
2016
|
-
|
|
2017
|
-
|
|
2016
|
+
logger3.log(`\u{1F680} Graph service is running on: ${baseUrl}`);
|
|
2017
|
+
logger3.log(`\u{1F4DA} API Documentation: http://localhost:${port}/api/docs`);
|
|
2018
2018
|
if (process.env.NODE_ENV !== "production") {
|
|
2019
|
-
|
|
2020
|
-
await registerWithServiceDiscovery(AppModule, port,
|
|
2019
|
+
logger3.debug(`Attempting service discovery registration (NODE_ENV: ${process.env.NODE_ENV || "undefined"})`);
|
|
2020
|
+
await registerWithServiceDiscovery(AppModule, port, logger3, app);
|
|
2021
2021
|
} else {
|
|
2022
|
-
|
|
2022
|
+
logger3.debug(`Skipping service discovery registration (NODE_ENV: ${process.env.NODE_ENV})`);
|
|
2023
2023
|
}
|
|
2024
2024
|
return app;
|
|
2025
2025
|
}
|
|
@@ -4872,7 +4872,7 @@ function clearAttachmentDataStore(threadId) {
|
|
|
4872
4872
|
}
|
|
4873
4873
|
__name(clearAttachmentDataStore, "clearAttachmentDataStore");
|
|
4874
4874
|
async function executeToolWithAttachments(params) {
|
|
4875
|
-
const { toolCall, mcpClient, enrichedArgs, executionContext, config, attachments, logger:
|
|
4875
|
+
const { toolCall, mcpClient, enrichedArgs, executionContext, config, attachments, logger: logger3, threshold = DEFAULT_ATTACHMENT_THRESHOLD, injectIntoArg = "data", sourceAttachmentId, threadId, toolSchema, mcpServers } = params;
|
|
4876
4876
|
const argsWithInjection = {
|
|
4877
4877
|
...enrichedArgs
|
|
4878
4878
|
};
|
|
@@ -4885,12 +4885,12 @@ async function executeToolWithAttachments(params) {
|
|
|
4885
4885
|
const data = storedData !== void 0 ? storedData : attachment.data;
|
|
4886
4886
|
if (data != null) {
|
|
4887
4887
|
argsWithInjection[injectIntoArg] = typeof data === "string" ? data : JSON.stringify(data);
|
|
4888
|
-
|
|
4888
|
+
logger3?.debug(`[Attachment] Auto-injected data from attachment "${attachment.toolCallId}" into ${toolCall.name}.${injectIntoArg} (source: ${storedData !== void 0 ? "memory" : "state"})`);
|
|
4889
4889
|
}
|
|
4890
4890
|
}
|
|
4891
4891
|
}
|
|
4892
4892
|
} catch (e) {
|
|
4893
|
-
|
|
4893
|
+
logger3?.warn(`[Attachment] Auto-injection failed: ${e}`);
|
|
4894
4894
|
}
|
|
4895
4895
|
const { content, success, rawResult } = await mcpClient.executeToolWithEvents(toolCall.id, toolCall.name, argsWithInjection, executionContext, config, mcpServers);
|
|
4896
4896
|
try {
|
|
@@ -4901,7 +4901,7 @@ async function executeToolWithAttachments(params) {
|
|
|
4901
4901
|
...attachment,
|
|
4902
4902
|
data: null
|
|
4903
4903
|
};
|
|
4904
|
-
|
|
4904
|
+
logger3?.debug(`[Attachment] Stored large result (${content.length} chars) as attachment "${toolCall.id}" (data in memory, metadata in state)`);
|
|
4905
4905
|
const toolMessage2 = new messages.ToolMessage({
|
|
4906
4906
|
content: attachment.summary,
|
|
4907
4907
|
tool_call_id: toolCall.id,
|
|
@@ -4916,7 +4916,7 @@ async function executeToolWithAttachments(params) {
|
|
|
4916
4916
|
};
|
|
4917
4917
|
}
|
|
4918
4918
|
} catch (e) {
|
|
4919
|
-
|
|
4919
|
+
logger3?.warn(`[Attachment] Failed to create attachment, using full content: ${e}`);
|
|
4920
4920
|
}
|
|
4921
4921
|
const toolMessage = new messages.ToolMessage({
|
|
4922
4922
|
content,
|
|
@@ -6230,7 +6230,7 @@ function createMetaBuilder(config, versionedGraphService, moduleRef) {
|
|
|
6230
6230
|
}
|
|
6231
6231
|
__name(createMetaBuilder, "createMetaBuilder");
|
|
6232
6232
|
function buildCheckpointerProviders(options) {
|
|
6233
|
-
const
|
|
6233
|
+
const logger3 = new common.Logger("UniversalGraphModule");
|
|
6234
6234
|
if (options.postgres !== void 0) {
|
|
6235
6235
|
return [
|
|
6236
6236
|
{
|
|
@@ -6244,7 +6244,7 @@ function buildCheckpointerProviders(options) {
|
|
|
6244
6244
|
if (!connString) {
|
|
6245
6245
|
throw new Error("[UniversalGraphModule] Postgres checkpointer: provide postgres.connectionString or set the DATABASE_URL environment variable.");
|
|
6246
6246
|
}
|
|
6247
|
-
|
|
6247
|
+
logger3.log(`Checkpointer: PostgreSQL (${connString.replace(/:[^:@]+@/, ":***@")})`);
|
|
6248
6248
|
const saver = PostgresSaver.fromConnString(connString, {
|
|
6249
6249
|
...options.postgres.schema ? {
|
|
6250
6250
|
schema: options.postgres.schema
|
|
@@ -6266,7 +6266,7 @@ function buildCheckpointerProviders(options) {
|
|
|
6266
6266
|
if (!mongoUri) {
|
|
6267
6267
|
throw new Error("[UniversalGraphModule] MongoDB checkpointer: provide mongodb.uri or set the MONGODB_URI environment variable.");
|
|
6268
6268
|
}
|
|
6269
|
-
|
|
6269
|
+
logger3.log(`Checkpointer: MongoDB (${mongoUri.substring(0, 50)}...)`);
|
|
6270
6270
|
await mongoose__default.default.connect(mongoUri, {
|
|
6271
6271
|
dbName
|
|
6272
6272
|
});
|
|
@@ -6300,7 +6300,7 @@ function buildCheckpointerProviders(options) {
|
|
|
6300
6300
|
provide: "CHECKPOINTER",
|
|
6301
6301
|
useFactory: /* @__PURE__ */ __name(async () => {
|
|
6302
6302
|
const { MemorySaver } = await import('@langchain/langgraph');
|
|
6303
|
-
|
|
6303
|
+
logger3.warn("Checkpointer: MemorySaver (in-process, no persistence). Configure postgres or mongodb in UniversalGraphModule.forRoot() for production.");
|
|
6304
6304
|
return new MemorySaver();
|
|
6305
6305
|
}, "useFactory")
|
|
6306
6306
|
}
|
|
@@ -6339,8 +6339,8 @@ exports.UniversalGraphModule = class _UniversalGraphModule {
|
|
|
6339
6339
|
const redisUrl = options.redis?.url ?? process.env.REDIS_URL;
|
|
6340
6340
|
if (redisUrl) {
|
|
6341
6341
|
const Redis2 = __require("ioredis");
|
|
6342
|
-
const
|
|
6343
|
-
|
|
6342
|
+
const logger3 = new common.Logger("UniversalGraphModule");
|
|
6343
|
+
logger3.log(`Callbacks: Redis (${redisUrl.replace(/:[^:@]+@/, ":***@")})`);
|
|
6344
6344
|
return new Redis2(redisUrl);
|
|
6345
6345
|
}
|
|
6346
6346
|
const IORedisMock = __require("ioredis-mock");
|
|
@@ -6624,7 +6624,7 @@ var McpConverter = class _McpConverter {
|
|
|
6624
6624
|
* Convert a single MCP tool to LangChain DynamicStructuredTool
|
|
6625
6625
|
*/
|
|
6626
6626
|
convertTool(mcpTool) {
|
|
6627
|
-
const
|
|
6627
|
+
const logger3 = this.logger;
|
|
6628
6628
|
const mcpRuntimeUrl = this.mcpRuntimeUrl;
|
|
6629
6629
|
let enhancedDescription = mcpTool.description;
|
|
6630
6630
|
if (mcpTool.inputSchema?.properties) {
|
|
@@ -6644,12 +6644,12 @@ ${paramDescriptions.join("\n")}`;
|
|
|
6644
6644
|
}
|
|
6645
6645
|
}
|
|
6646
6646
|
const schema = this.jsonSchemaToZod(mcpTool.inputSchema);
|
|
6647
|
-
|
|
6648
|
-
|
|
6647
|
+
logger3.debug(`\u{1F527} [${mcpTool.name}] Original schema:`, JSON.stringify(mcpTool.inputSchema, null, 2));
|
|
6648
|
+
logger3.debug(`\u{1F527} [${mcpTool.name}] Using schema type: ${schema?._def?.typeName ?? "unknown"}`);
|
|
6649
6649
|
if (schema?._def?.shape && typeof schema._def.shape === "function") {
|
|
6650
6650
|
try {
|
|
6651
6651
|
const shape = schema._def.shape();
|
|
6652
|
-
|
|
6652
|
+
logger3.debug(`\u{1F527} [${mcpTool.name}] Converted Zod schema shape:`, JSON.stringify(Object.entries(shape).reduce((acc, [key, val]) => {
|
|
6653
6653
|
acc[key] = {
|
|
6654
6654
|
type: val?._def?.typeName,
|
|
6655
6655
|
description: val?._def?.description,
|
|
@@ -6658,50 +6658,50 @@ ${paramDescriptions.join("\n")}`;
|
|
|
6658
6658
|
return acc;
|
|
6659
6659
|
}, {}), null, 2));
|
|
6660
6660
|
} catch (error) {
|
|
6661
|
-
|
|
6661
|
+
logger3.debug(`\u{1F527} [${mcpTool.name}] Could not extract Zod schema shape: ${error}`);
|
|
6662
6662
|
}
|
|
6663
6663
|
}
|
|
6664
6664
|
try {
|
|
6665
6665
|
const convertedJsonSchema = zodToJsonSchema.zodToJsonSchema(schema);
|
|
6666
|
-
|
|
6666
|
+
logger3.warn(`\u{1F527} [${mcpTool.name}] JSON Schema that LangChain will use:`, JSON.stringify(convertedJsonSchema, null, 2));
|
|
6667
6667
|
} catch (error) {
|
|
6668
|
-
|
|
6668
|
+
logger3.warn(`\u{1F527} [${mcpTool.name}] Could not convert Zod to JSON Schema: ${error}`);
|
|
6669
6669
|
}
|
|
6670
6670
|
return new tools.DynamicStructuredTool({
|
|
6671
6671
|
name: mcpTool.name,
|
|
6672
6672
|
description: enhancedDescription,
|
|
6673
6673
|
schema,
|
|
6674
6674
|
func: /* @__PURE__ */ __name(async (input, _runManager, config) => {
|
|
6675
|
-
|
|
6675
|
+
logger3.log(`\u{1F527} [${mcpTool.name}] LLM INPUT: ${JSON.stringify(input)}`);
|
|
6676
6676
|
const configurable = config?.configurable;
|
|
6677
6677
|
const context = {
|
|
6678
6678
|
agentId: configurable?.agentId,
|
|
6679
6679
|
userId: configurable?.userId,
|
|
6680
6680
|
threadId: configurable?.thread_id
|
|
6681
6681
|
};
|
|
6682
|
-
|
|
6682
|
+
logger3.debug(`\u{1F527} [${mcpTool.name}] Execution context: ${JSON.stringify(context)}`);
|
|
6683
6683
|
try {
|
|
6684
6684
|
const request = {
|
|
6685
6685
|
name: mcpTool.name,
|
|
6686
6686
|
arguments: input ?? {},
|
|
6687
6687
|
context
|
|
6688
6688
|
};
|
|
6689
|
-
|
|
6689
|
+
logger3.log(`\u{1F527} [${mcpTool.name}] Calling MCP Runtime...`);
|
|
6690
6690
|
const response = await axios2__default.default.post(`${mcpRuntimeUrl}/tools/execute`, request, {
|
|
6691
6691
|
timeout: 3e4
|
|
6692
6692
|
});
|
|
6693
6693
|
const result = response.data;
|
|
6694
|
-
|
|
6694
|
+
logger3.log(`\u{1F527} [${mcpTool.name}] MCP Runtime response: success=${result.success}`);
|
|
6695
6695
|
if (!result.success) {
|
|
6696
6696
|
const errorMessage = result.error || "Tool execution failed";
|
|
6697
|
-
|
|
6697
|
+
logger3.error(`\u{1F527} [${mcpTool.name}] MCP Runtime error: ${errorMessage}`);
|
|
6698
6698
|
throw new Error(errorMessage);
|
|
6699
6699
|
}
|
|
6700
6700
|
const output = typeof result.result === "string" ? result.result : JSON.stringify(result.result, null, 2);
|
|
6701
|
-
|
|
6701
|
+
logger3.log(`\u{1F527} [${mcpTool.name}] TOOL OUTPUT: ${output.length > 200 ? output.substring(0, 200) + "..." : output}`);
|
|
6702
6702
|
return output;
|
|
6703
6703
|
} catch (error) {
|
|
6704
|
-
|
|
6704
|
+
logger3.error(`\u{1F527} [${mcpTool.name}] Exception during execution`, error);
|
|
6705
6705
|
if (axios2__default.default.isAxiosError(error)) {
|
|
6706
6706
|
throw new Error(`MCP Runtime error: ${error.message}`);
|
|
6707
6707
|
}
|
|
@@ -7076,6 +7076,110 @@ function isReasoningModel(modelName) {
|
|
|
7076
7076
|
return modelName.includes("gpt-5") || modelName.includes("gpt-o1") || modelName.includes("gpt-o2") || modelName.includes("gpt-o3") || modelName.includes("gpt-o4") || /^gpt-(5|6|7|8|9)/.test(modelName) || /^gpt-o[1-4]/.test(modelName);
|
|
7077
7077
|
}
|
|
7078
7078
|
__name(isReasoningModel, "isReasoningModel");
|
|
7079
|
+
function toOptionalNumber(value) {
|
|
7080
|
+
if (value === void 0 || value === null || value === "") return void 0;
|
|
7081
|
+
const n = Number(value);
|
|
7082
|
+
return Number.isFinite(n) ? n : void 0;
|
|
7083
|
+
}
|
|
7084
|
+
__name(toOptionalNumber, "toOptionalNumber");
|
|
7085
|
+
var SAMPLING_PARAM_FREE_THRESHOLDS = {
|
|
7086
|
+
opus: {
|
|
7087
|
+
major: 4,
|
|
7088
|
+
minor: 7
|
|
7089
|
+
},
|
|
7090
|
+
sonnet: {
|
|
7091
|
+
major: 5,
|
|
7092
|
+
minor: 0
|
|
7093
|
+
},
|
|
7094
|
+
haiku: {
|
|
7095
|
+
major: 5,
|
|
7096
|
+
minor: 0
|
|
7097
|
+
}
|
|
7098
|
+
};
|
|
7099
|
+
var SAMPLING_PARAM_FREE_FAMILIES = /claude-(fable|mythos)\b/;
|
|
7100
|
+
var CLAUDE_FAMILY_VERSION = /claude-(opus|sonnet|haiku)-(\d{1,2})(?:-(\d{1,2}))?(?![\d.])/;
|
|
7101
|
+
function modelAcceptsSamplingParams(modelIdentifier) {
|
|
7102
|
+
if (!modelIdentifier) return true;
|
|
7103
|
+
const id = modelIdentifier.toLowerCase();
|
|
7104
|
+
if (SAMPLING_PARAM_FREE_FAMILIES.test(id)) return false;
|
|
7105
|
+
const match = CLAUDE_FAMILY_VERSION.exec(id);
|
|
7106
|
+
if (!match) return true;
|
|
7107
|
+
const [, family, majorRaw, minorRaw] = match;
|
|
7108
|
+
const threshold = SAMPLING_PARAM_FREE_THRESHOLDS[family];
|
|
7109
|
+
if (!threshold) return true;
|
|
7110
|
+
const major = Number(majorRaw);
|
|
7111
|
+
const minor = minorRaw === void 0 ? 0 : Number(minorRaw);
|
|
7112
|
+
const atOrAboveThreshold = major > threshold.major || major === threshold.major && minor >= threshold.minor;
|
|
7113
|
+
return !atOrAboveThreshold;
|
|
7114
|
+
}
|
|
7115
|
+
__name(modelAcceptsSamplingParams, "modelAcceptsSamplingParams");
|
|
7116
|
+
var PROMPT_CACHE_MIN_VERSIONS = {
|
|
7117
|
+
opus: {
|
|
7118
|
+
major: 4,
|
|
7119
|
+
minor: 0
|
|
7120
|
+
},
|
|
7121
|
+
sonnet: {
|
|
7122
|
+
major: 4,
|
|
7123
|
+
minor: 0
|
|
7124
|
+
},
|
|
7125
|
+
haiku: {
|
|
7126
|
+
major: 4,
|
|
7127
|
+
minor: 5
|
|
7128
|
+
}
|
|
7129
|
+
};
|
|
7130
|
+
function modelSupportsPromptCache(modelIdentifier) {
|
|
7131
|
+
if (!modelIdentifier) return false;
|
|
7132
|
+
const match = CLAUDE_FAMILY_VERSION.exec(modelIdentifier.toLowerCase());
|
|
7133
|
+
if (!match) return false;
|
|
7134
|
+
const [, family, majorRaw, minorRaw] = match;
|
|
7135
|
+
const threshold = PROMPT_CACHE_MIN_VERSIONS[family];
|
|
7136
|
+
if (!threshold) return false;
|
|
7137
|
+
const major = Number(majorRaw);
|
|
7138
|
+
const minor = minorRaw === void 0 ? 0 : Number(minorRaw);
|
|
7139
|
+
return major > threshold.major || major === threshold.major && minor >= threshold.minor;
|
|
7140
|
+
}
|
|
7141
|
+
__name(modelSupportsPromptCache, "modelSupportsPromptCache");
|
|
7142
|
+
function resolvePromptCacheControl(modelIdentifiers, promptCache, ttl) {
|
|
7143
|
+
const enabled = promptCache ?? modelIdentifiers.some((id) => modelSupportsPromptCache(id));
|
|
7144
|
+
return enabled ? {
|
|
7145
|
+
type: "ephemeral",
|
|
7146
|
+
ttl: ttl ?? "5m"
|
|
7147
|
+
} : void 0;
|
|
7148
|
+
}
|
|
7149
|
+
__name(resolvePromptCacheControl, "resolvePromptCacheControl");
|
|
7150
|
+
function buildEffortRequestFields(effort) {
|
|
7151
|
+
return effort ? {
|
|
7152
|
+
output_config: {
|
|
7153
|
+
effort
|
|
7154
|
+
}
|
|
7155
|
+
} : void 0;
|
|
7156
|
+
}
|
|
7157
|
+
__name(buildEffortRequestFields, "buildEffortRequestFields");
|
|
7158
|
+
function resolveSamplingParams(modelIdentifiers, requested, supportsSamplingParams) {
|
|
7159
|
+
const accepted = supportsSamplingParams ?? modelIdentifiers.every((id) => modelAcceptsSamplingParams(id));
|
|
7160
|
+
if (accepted) {
|
|
7161
|
+
const params = {};
|
|
7162
|
+
if (requested.temperature !== void 0) params.temperature = requested.temperature;
|
|
7163
|
+
if (requested.topP !== void 0) params.topP = requested.topP;
|
|
7164
|
+
if (requested.topK !== void 0) params.topK = requested.topK;
|
|
7165
|
+
return {
|
|
7166
|
+
params,
|
|
7167
|
+
dropped: [],
|
|
7168
|
+
accepted: true
|
|
7169
|
+
};
|
|
7170
|
+
}
|
|
7171
|
+
const dropped = [
|
|
7172
|
+
"temperature",
|
|
7173
|
+
"topP",
|
|
7174
|
+
"topK"
|
|
7175
|
+
].filter((key) => requested[key] !== void 0);
|
|
7176
|
+
return {
|
|
7177
|
+
params: {},
|
|
7178
|
+
dropped,
|
|
7179
|
+
accepted: false
|
|
7180
|
+
};
|
|
7181
|
+
}
|
|
7182
|
+
__name(resolveSamplingParams, "resolveSamplingParams");
|
|
7079
7183
|
function hashToolsConfig(toolsConfig) {
|
|
7080
7184
|
const sorted = toolsConfig.map((t) => `${t.toolName}:${t.enabled}:${JSON.stringify(t.config || {})}`).sort().join("|");
|
|
7081
7185
|
return crypto.createHash("md5").update(sorted).digest("hex").slice(0, 16);
|
|
@@ -7128,13 +7232,122 @@ function buildOpenAIModelConfig(modelName, temperature, maxTokens, apiToken) {
|
|
|
7128
7232
|
}
|
|
7129
7233
|
return {
|
|
7130
7234
|
modelName,
|
|
7131
|
-
|
|
7235
|
+
// Omit the key entirely when absent — an explicit `undefined` would still
|
|
7236
|
+
// be enumerable and can be forwarded as a null-ish value downstream.
|
|
7237
|
+
...temperature !== void 0 && {
|
|
7238
|
+
temperature
|
|
7239
|
+
},
|
|
7132
7240
|
maxTokens,
|
|
7133
7241
|
streaming: true,
|
|
7134
7242
|
openAIApiKey: apiToken
|
|
7135
7243
|
};
|
|
7136
7244
|
}
|
|
7137
7245
|
__name(buildOpenAIModelConfig, "buildOpenAIModelConfig");
|
|
7246
|
+
|
|
7247
|
+
// src/models/reasoning-content.logic.ts
|
|
7248
|
+
function isReasoningBlock(block) {
|
|
7249
|
+
return typeof block === "object" && block !== null && block.type === "reasoning_content";
|
|
7250
|
+
}
|
|
7251
|
+
__name(isReasoningBlock, "isReasoningBlock");
|
|
7252
|
+
function isSendableReasoningBlock(block) {
|
|
7253
|
+
if (typeof block.redactedContent === "string" && block.redactedContent !== "") return true;
|
|
7254
|
+
const text = block.reasoningText?.text;
|
|
7255
|
+
return typeof text === "string" && text !== "";
|
|
7256
|
+
}
|
|
7257
|
+
__name(isSendableReasoningBlock, "isSendableReasoningBlock");
|
|
7258
|
+
function normalizeUnsendableBlock(block) {
|
|
7259
|
+
const signature = block.reasoningText?.signature;
|
|
7260
|
+
if (typeof signature !== "string" || signature === "") return null;
|
|
7261
|
+
return {
|
|
7262
|
+
type: "reasoning_content",
|
|
7263
|
+
reasoningText: {
|
|
7264
|
+
text: "",
|
|
7265
|
+
signature
|
|
7266
|
+
}
|
|
7267
|
+
};
|
|
7268
|
+
}
|
|
7269
|
+
__name(normalizeUnsendableBlock, "normalizeUnsendableBlock");
|
|
7270
|
+
function hasToolCalls(message) {
|
|
7271
|
+
const toolCalls = message.tool_calls;
|
|
7272
|
+
return Array.isArray(toolCalls) && toolCalls.length > 0;
|
|
7273
|
+
}
|
|
7274
|
+
__name(hasToolCalls, "hasToolCalls");
|
|
7275
|
+
function withContent(message, content) {
|
|
7276
|
+
const clone = Object.assign(Object.create(Object.getPrototypeOf(message)), message, {
|
|
7277
|
+
content
|
|
7278
|
+
});
|
|
7279
|
+
if (clone.lc_kwargs) clone.lc_kwargs = {
|
|
7280
|
+
...clone.lc_kwargs,
|
|
7281
|
+
content
|
|
7282
|
+
};
|
|
7283
|
+
return clone;
|
|
7284
|
+
}
|
|
7285
|
+
__name(withContent, "withContent");
|
|
7286
|
+
function sanitizeMessageReasoning(message) {
|
|
7287
|
+
if (message.getType() !== "ai") return message;
|
|
7288
|
+
const content = message.content;
|
|
7289
|
+
if (!Array.isArray(content)) return message;
|
|
7290
|
+
const unsendable = content.filter((block) => isReasoningBlock(block) && !isSendableReasoningBlock(block));
|
|
7291
|
+
if (unsendable.length === 0) return message;
|
|
7292
|
+
const kept = content.filter((block) => !unsendable.includes(block));
|
|
7293
|
+
if (kept.length === 0 && !hasToolCalls(message)) {
|
|
7294
|
+
for (let i = unsendable.length - 1; i >= 0; i--) {
|
|
7295
|
+
const normalized = normalizeUnsendableBlock(unsendable[i]);
|
|
7296
|
+
if (normalized) return withContent(message, [
|
|
7297
|
+
normalized
|
|
7298
|
+
]);
|
|
7299
|
+
}
|
|
7300
|
+
}
|
|
7301
|
+
return withContent(message, kept);
|
|
7302
|
+
}
|
|
7303
|
+
__name(sanitizeMessageReasoning, "sanitizeMessageReasoning");
|
|
7304
|
+
function sanitizeReasoningForBedrock(messages) {
|
|
7305
|
+
let sanitized = 0;
|
|
7306
|
+
let next;
|
|
7307
|
+
for (let i = 0; i < messages.length; i++) {
|
|
7308
|
+
const cleaned = sanitizeMessageReasoning(messages[i]);
|
|
7309
|
+
if (cleaned === messages[i]) continue;
|
|
7310
|
+
if (!next) next = [
|
|
7311
|
+
...messages
|
|
7312
|
+
];
|
|
7313
|
+
next[i] = cleaned;
|
|
7314
|
+
const before = messages[i].content.length;
|
|
7315
|
+
const after = cleaned.content.length;
|
|
7316
|
+
sanitized += Math.max(1, before - after);
|
|
7317
|
+
}
|
|
7318
|
+
return {
|
|
7319
|
+
messages: next ?? messages,
|
|
7320
|
+
sanitized
|
|
7321
|
+
};
|
|
7322
|
+
}
|
|
7323
|
+
__name(sanitizeReasoningForBedrock, "sanitizeReasoningForBedrock");
|
|
7324
|
+
|
|
7325
|
+
// src/models/bedrock-chat-model.ts
|
|
7326
|
+
var logger2 = new common.Logger("FlutchChatBedrockConverse");
|
|
7327
|
+
var FlutchChatBedrockConverse = class extends aws.ChatBedrockConverse {
|
|
7328
|
+
static {
|
|
7329
|
+
__name(this, "FlutchChatBedrockConverse");
|
|
7330
|
+
}
|
|
7331
|
+
static lc_name() {
|
|
7332
|
+
return "FlutchChatBedrockConverse";
|
|
7333
|
+
}
|
|
7334
|
+
sanitize(messages) {
|
|
7335
|
+
const { messages: cleaned, sanitized } = sanitizeReasoningForBedrock(messages);
|
|
7336
|
+
if (sanitized > 0) {
|
|
7337
|
+
logger2.debug(`Dropped ${sanitized} unsendable reasoning block(s) from outgoing history (model=${this.model})`);
|
|
7338
|
+
}
|
|
7339
|
+
return cleaned;
|
|
7340
|
+
}
|
|
7341
|
+
/** `.invoke()` / `.generate()` path. */
|
|
7342
|
+
async _generate(messages, options, runManager) {
|
|
7343
|
+
return super._generate(this.sanitize(messages), options, runManager);
|
|
7344
|
+
}
|
|
7345
|
+
/** `.stream()` / `streamEvents()` path (also used by `_generate` when the
|
|
7346
|
+
* model is constructed with `streaming: true` — sanitizing is idempotent). */
|
|
7347
|
+
async *_streamResponseChunks(messages, options, runManager) {
|
|
7348
|
+
yield* super._streamResponseChunks(this.sanitize(messages), options, runManager);
|
|
7349
|
+
}
|
|
7350
|
+
};
|
|
7138
7351
|
var VoyageAIRerank = class extends document_compressors.BaseDocumentCompressor {
|
|
7139
7352
|
static {
|
|
7140
7353
|
__name(this, "VoyageAIRerank");
|
|
@@ -7206,10 +7419,10 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
7206
7419
|
[ModelProvider.COHERE]: "COHERE_API_KEY",
|
|
7207
7420
|
[ModelProvider.VOYAGEAI]: "VOYAGEAI_API_KEY"
|
|
7208
7421
|
};
|
|
7209
|
-
constructor(configFetcher,
|
|
7422
|
+
constructor(configFetcher, logger3, apiKeyResolver) {
|
|
7210
7423
|
this.configFetcher = configFetcher;
|
|
7211
7424
|
this.apiKeyResolver = apiKeyResolver;
|
|
7212
|
-
this.logger =
|
|
7425
|
+
this.logger = logger3 || new common.Logger(_ModelInitializer.name);
|
|
7213
7426
|
}
|
|
7214
7427
|
/**
|
|
7215
7428
|
* Resolve API key for a provider.
|
|
@@ -7232,6 +7445,32 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
7232
7445
|
return process.env.BEDROCK_AWS_REGION || process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || "us-east-1";
|
|
7233
7446
|
}
|
|
7234
7447
|
/**
|
|
7448
|
+
* Resolve sampling parameters for a model, dropping them when the model
|
|
7449
|
+
* does not accept them (Claude Opus 4.7+, Claude 5 and newer).
|
|
7450
|
+
*
|
|
7451
|
+
* An explicitly requested value on such a model is **ignored with a warning**
|
|
7452
|
+
* rather than raising: the request must keep working, and the model runs at
|
|
7453
|
+
* its own default sampling behaviour. Pass `supportsSamplingParams: true` in
|
|
7454
|
+
* the config to force the params through anyway.
|
|
7455
|
+
*
|
|
7456
|
+
* @param modelIdentifiers every name the model is known by (catalog model
|
|
7457
|
+
* name, Bedrock model id, …) — a match on any of them drops the params
|
|
7458
|
+
* @param wasExplicit whether the caller explicitly asked for these values
|
|
7459
|
+
* (as opposed to inheriting a catalog/SDK default) — controls log level
|
|
7460
|
+
*/
|
|
7461
|
+
resolveSampling(modelIdentifiers, requested, supportsSamplingParams, wasExplicit = false) {
|
|
7462
|
+
const resolved = resolveSamplingParams(modelIdentifiers, requested, supportsSamplingParams);
|
|
7463
|
+
if (!resolved.accepted && resolved.dropped.length > 0) {
|
|
7464
|
+
const message = `Model ${modelIdentifiers.filter(Boolean).join(" / ")} does not accept sampling parameters \u2014 ignoring ${resolved.dropped.join(", ")}. Set supportsSamplingParams: true to override.`;
|
|
7465
|
+
if (wasExplicit) {
|
|
7466
|
+
this.logger.warn(message);
|
|
7467
|
+
} else {
|
|
7468
|
+
this.logger.debug(message);
|
|
7469
|
+
}
|
|
7470
|
+
}
|
|
7471
|
+
return resolved.params;
|
|
7472
|
+
}
|
|
7473
|
+
/**
|
|
7235
7474
|
* Generate hash from toolsConfig for cache key
|
|
7236
7475
|
* Uses MD5 hash to create short, unique identifier
|
|
7237
7476
|
*/
|
|
@@ -7245,10 +7484,10 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
7245
7484
|
*/
|
|
7246
7485
|
generateModelCacheKey(config) {
|
|
7247
7486
|
const base = generateModelCacheKey(config.modelId, config.temperature, config.maxTokens, config.toolsConfig, config.baseURL);
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
}
|
|
7251
|
-
return
|
|
7487
|
+
const withMcp = config.mcpServers && config.mcpServers.length > 0 ? `${base}:mcp:${JSON.stringify(config.mcpServers)}` : base;
|
|
7488
|
+
const withSampling = config.supportsSamplingParams === void 0 ? withMcp : `${withMcp}:sp:${config.supportsSamplingParams}`;
|
|
7489
|
+
const withCache = config.promptCache === void 0 && config.promptCacheTtl === void 0 ? withSampling : `${withSampling}:pc:${config.promptCache ?? "auto"}:${config.promptCacheTtl ?? "default"}`;
|
|
7490
|
+
return config.effort === void 0 ? withCache : `${withCache}:eff:${config.effort}`;
|
|
7252
7491
|
}
|
|
7253
7492
|
// Chat model creators
|
|
7254
7493
|
chatModelCreators = {
|
|
@@ -7263,12 +7502,23 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
7263
7502
|
}
|
|
7264
7503
|
return new openai.ChatOpenAI(config);
|
|
7265
7504
|
},
|
|
7266
|
-
[ModelProvider.ANTHROPIC]: ({ modelName, defaultTemperature, defaultMaxTokens, apiToken, baseURL }) => {
|
|
7505
|
+
[ModelProvider.ANTHROPIC]: ({ modelName, defaultTemperature, defaultMaxTokens, apiToken, baseURL }, promptCacheControl) => {
|
|
7267
7506
|
const routerURL = resolveRouterURL(baseURL);
|
|
7268
7507
|
return new anthropic.ChatAnthropic({
|
|
7269
7508
|
modelName,
|
|
7270
|
-
temperature
|
|
7509
|
+
// Claude Opus 4.7+ / Claude 5 reject `temperature` outright — the key
|
|
7510
|
+
// must be absent, not `undefined`.
|
|
7511
|
+
...defaultTemperature !== void 0 && {
|
|
7512
|
+
temperature: defaultTemperature
|
|
7513
|
+
},
|
|
7271
7514
|
maxTokens: defaultMaxTokens,
|
|
7515
|
+
// Top-level prompt caching: one breakpoint on the last cacheable block,
|
|
7516
|
+
// advanced automatically as the conversation grows. Survives the router
|
|
7517
|
+
// (which forwards the Anthropic body untouched) and is accepted by
|
|
7518
|
+
// Bedrock's InvokeModel schema behind it.
|
|
7519
|
+
...promptCacheControl && {
|
|
7520
|
+
cache_control: promptCacheControl
|
|
7521
|
+
},
|
|
7272
7522
|
anthropicApiKey: apiToken || this.resolveApiKey(ModelProvider.ANTHROPIC),
|
|
7273
7523
|
...routerURL && {
|
|
7274
7524
|
anthropicApiUrl: routerURL,
|
|
@@ -7283,7 +7533,9 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
7283
7533
|
const token = apiToken || this.resolveApiKey(ModelProvider.COHERE);
|
|
7284
7534
|
return routerURL ? new cohere.ChatCohere({
|
|
7285
7535
|
model: modelName,
|
|
7286
|
-
|
|
7536
|
+
...defaultTemperature !== void 0 && {
|
|
7537
|
+
temperature: defaultTemperature
|
|
7538
|
+
},
|
|
7287
7539
|
client: new cohereAi.CohereClient({
|
|
7288
7540
|
token,
|
|
7289
7541
|
baseUrl: routerURL,
|
|
@@ -7293,7 +7545,9 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
7293
7545
|
})
|
|
7294
7546
|
}) : new cohere.ChatCohere({
|
|
7295
7547
|
model: modelName,
|
|
7296
|
-
|
|
7548
|
+
...defaultTemperature !== void 0 && {
|
|
7549
|
+
temperature: defaultTemperature
|
|
7550
|
+
},
|
|
7297
7551
|
apiKey: token
|
|
7298
7552
|
});
|
|
7299
7553
|
},
|
|
@@ -7301,7 +7555,9 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
7301
7555
|
const routerURL = resolveRouterURL(baseURL);
|
|
7302
7556
|
return new mistralai.ChatMistralAI({
|
|
7303
7557
|
model: modelName,
|
|
7304
|
-
|
|
7558
|
+
...defaultTemperature !== void 0 && {
|
|
7559
|
+
temperature: defaultTemperature
|
|
7560
|
+
},
|
|
7305
7561
|
maxTokens: defaultMaxTokens,
|
|
7306
7562
|
apiKey: apiToken || this.resolveApiKey(ModelProvider.MISTRAL),
|
|
7307
7563
|
...routerURL && {
|
|
@@ -7391,7 +7647,8 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
7391
7647
|
async initializeChatModelDirect(config, customTools) {
|
|
7392
7648
|
const toolsConfig = normalizeToolConfigs(config.tools);
|
|
7393
7649
|
const modelIdentifier = `${config.provider}:${config.modelName}`;
|
|
7394
|
-
const
|
|
7650
|
+
const baseCacheKey = generateModelCacheKey(modelIdentifier, config.temperature, config.maxTokens, toolsConfig, config.baseURL);
|
|
7651
|
+
const cacheKey = config.supportsSamplingParams === void 0 ? baseCacheKey : `${baseCacheKey}:sp:${config.supportsSamplingParams}`;
|
|
7395
7652
|
const cached = this.modelInstanceCache.get(cacheKey);
|
|
7396
7653
|
if (cached) {
|
|
7397
7654
|
this.logger.debug(`Using cached chat model instance: ${cacheKey}`);
|
|
@@ -7402,18 +7659,23 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
7402
7659
|
throw new Error(`Unknown provider "${provider}". Valid: ${Object.values(ModelProvider).join(", ")}`);
|
|
7403
7660
|
}
|
|
7404
7661
|
const apiToken = this.resolveApiKey(provider);
|
|
7405
|
-
const
|
|
7406
|
-
const
|
|
7662
|
+
const maxTokens = toOptionalNumber(config.maxTokens) ?? 4096;
|
|
7663
|
+
const sampling = this.resolveSampling([
|
|
7664
|
+
config.modelName
|
|
7665
|
+
], {
|
|
7666
|
+
temperature: toOptionalNumber(config.temperature) ?? 0.7
|
|
7667
|
+
}, config.supportsSamplingParams, config.temperature !== void 0);
|
|
7407
7668
|
const modelConfig = {
|
|
7408
7669
|
modelId: modelIdentifier,
|
|
7409
7670
|
modelName: config.modelName,
|
|
7410
7671
|
provider,
|
|
7411
7672
|
modelType: ModelType.CHAT,
|
|
7412
|
-
defaultTemperature:
|
|
7413
|
-
defaultMaxTokens:
|
|
7673
|
+
defaultTemperature: sampling.temperature,
|
|
7674
|
+
defaultMaxTokens: maxTokens,
|
|
7414
7675
|
apiToken,
|
|
7415
7676
|
requiresApiKey: true,
|
|
7416
|
-
baseURL: config.baseURL
|
|
7677
|
+
baseURL: config.baseURL,
|
|
7678
|
+
supportsSamplingParams: config.supportsSamplingParams
|
|
7417
7679
|
};
|
|
7418
7680
|
this.logger.debug(`Creating chat model: ${modelIdentifier} (apiKeyResolved=${!!apiToken})`);
|
|
7419
7681
|
const creator = this.chatModelCreators[provider];
|
|
@@ -7448,19 +7710,40 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
7448
7710
|
if (modelConfig.modelType !== ModelType.CHAT) {
|
|
7449
7711
|
throw new Error(`Model ${config.modelId} is not a chat model (type: ${modelConfig.modelType})`);
|
|
7450
7712
|
}
|
|
7713
|
+
const requestedTemperature = toOptionalNumber(config.temperature) ?? toOptionalNumber(modelConfig.defaultTemperature);
|
|
7714
|
+
const sampling = this.resolveSampling([
|
|
7715
|
+
modelConfig.modelName,
|
|
7716
|
+
modelConfig.bedrockModelId
|
|
7717
|
+
], {
|
|
7718
|
+
temperature: requestedTemperature
|
|
7719
|
+
}, config.supportsSamplingParams ?? modelConfig.supportsSamplingParams, config.temperature !== void 0);
|
|
7451
7720
|
const finalConfig = {
|
|
7452
7721
|
...modelConfig,
|
|
7453
|
-
defaultTemperature:
|
|
7454
|
-
defaultMaxTokens:
|
|
7722
|
+
defaultTemperature: sampling.temperature,
|
|
7723
|
+
defaultMaxTokens: toOptionalNumber(config.maxTokens) ?? toOptionalNumber(modelConfig.defaultMaxTokens),
|
|
7455
7724
|
baseURL: config.baseURL ?? modelConfig.baseURL
|
|
7456
7725
|
};
|
|
7726
|
+
const promptCacheControl = resolvePromptCacheControl([
|
|
7727
|
+
finalConfig.bedrockModelId,
|
|
7728
|
+
finalConfig.modelName
|
|
7729
|
+
], config.promptCache ?? modelConfig.promptCache, config.promptCacheTtl ?? modelConfig.promptCacheTtl);
|
|
7730
|
+
if (promptCacheControl) {
|
|
7731
|
+
this.logger.debug(`Prompt caching enabled for ${finalConfig.bedrockModelId ?? finalConfig.modelName} (ttl=${promptCacheControl.ttl})`);
|
|
7732
|
+
}
|
|
7457
7733
|
this.logger.debug(`Creating new chat model instance: ${cacheKey}`);
|
|
7458
7734
|
let model;
|
|
7459
7735
|
if (finalConfig.useBedrock && finalConfig.bedrockModelId) {
|
|
7460
|
-
|
|
7736
|
+
const effortFields = buildEffortRequestFields(config.effort ?? modelConfig.defaultEffort);
|
|
7737
|
+
model = new FlutchChatBedrockConverse({
|
|
7461
7738
|
model: finalConfig.bedrockModelId,
|
|
7462
7739
|
region: this.resolveBedrockRegion(),
|
|
7463
|
-
|
|
7740
|
+
// Key omitted (not `undefined`) for models that reject sampling params.
|
|
7741
|
+
...finalConfig.defaultTemperature !== void 0 && {
|
|
7742
|
+
temperature: finalConfig.defaultTemperature
|
|
7743
|
+
},
|
|
7744
|
+
...effortFields && {
|
|
7745
|
+
additionalModelRequestFields: effortFields
|
|
7746
|
+
},
|
|
7464
7747
|
maxTokens: finalConfig.defaultMaxTokens,
|
|
7465
7748
|
streaming: true
|
|
7466
7749
|
});
|
|
@@ -7469,14 +7752,24 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
7469
7752
|
if (!creator) {
|
|
7470
7753
|
throw new Error(`Chat models not supported for provider: ${modelConfig.provider}`);
|
|
7471
7754
|
}
|
|
7472
|
-
model = creator(finalConfig);
|
|
7755
|
+
model = creator(finalConfig, promptCacheControl);
|
|
7473
7756
|
}
|
|
7474
7757
|
model.metadata = {
|
|
7475
7758
|
...model.metadata,
|
|
7476
7759
|
modelId: config.modelId
|
|
7477
7760
|
};
|
|
7478
7761
|
if (config.toolsConfig || config.customTools || config.mcpServers && config.mcpServers.length > 0) {
|
|
7479
|
-
const boundModel = await this.bindToolsToModel(
|
|
7762
|
+
const boundModel = await this.bindToolsToModel(
|
|
7763
|
+
model,
|
|
7764
|
+
config.toolsConfig,
|
|
7765
|
+
config.customTools,
|
|
7766
|
+
config.mcpServers,
|
|
7767
|
+
config.mcpContext,
|
|
7768
|
+
// Converse takes cache control as a per-call option; the Anthropic
|
|
7769
|
+
// client already got it as a constructor field, and handing it the
|
|
7770
|
+
// same value twice would put an unknown key in its call options.
|
|
7771
|
+
finalConfig.useBedrock ? promptCacheControl : void 0
|
|
7772
|
+
);
|
|
7480
7773
|
this.modelInstanceCache.set(cacheKey, boundModel);
|
|
7481
7774
|
return boundModel;
|
|
7482
7775
|
}
|
|
@@ -7488,11 +7781,20 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
7488
7781
|
* For toolsConfig: fetch tool executors from MCP Runtime
|
|
7489
7782
|
* For customTools: use as-is (already prepared DynamicStructuredTool)
|
|
7490
7783
|
*
|
|
7784
|
+
* `promptCacheControl` is the **Bedrock-only** half of prompt caching: it is
|
|
7785
|
+
* bound alongside the tools as a default call option, and `ChatBedrockConverse`
|
|
7786
|
+
* turns it into `cachePoint` blocks after the tool schemas, the system prompt
|
|
7787
|
+
* and the last message. Tool schemas dominate the request, so this is the one
|
|
7788
|
+
* place worth caching — a model with no tools keeps its plain `BaseChatModel`
|
|
7789
|
+
* type and no cache points (callers there rely on `withStructuredOutput` and
|
|
7790
|
+
* friends). The Anthropic client takes its cache settings in the constructor
|
|
7791
|
+
* instead and must not be handed them again here.
|
|
7792
|
+
*
|
|
7491
7793
|
* Returns:
|
|
7492
7794
|
* - Runnable when tools are bound (model.bindTools returns Runnable)
|
|
7493
7795
|
* - BaseChatModel when no tools
|
|
7494
7796
|
*/
|
|
7495
|
-
async bindToolsToModel(model, toolsConfig, customTools, mcpServers, mcpContext) {
|
|
7797
|
+
async bindToolsToModel(model, toolsConfig, customTools, mcpServers, mcpContext, promptCacheControl) {
|
|
7496
7798
|
const allTools = [];
|
|
7497
7799
|
const enabledToolsConfig = (toolsConfig || []).filter((tc) => tc.enabled !== false);
|
|
7498
7800
|
const hasInlineServers = !!(mcpServers && mcpServers.length > 0);
|
|
@@ -7513,7 +7815,10 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
7513
7815
|
}
|
|
7514
7816
|
if (allTools.length > 0) {
|
|
7515
7817
|
this.logger.debug(`Binding ${allTools.length} tools to model`);
|
|
7516
|
-
const
|
|
7818
|
+
const boundOptions = {
|
|
7819
|
+
cache_control: promptCacheControl
|
|
7820
|
+
};
|
|
7821
|
+
const modelWithTools = promptCacheControl ? model.bindTools(allTools, boundOptions) : model.bindTools(allTools);
|
|
7517
7822
|
return modelWithTools;
|
|
7518
7823
|
}
|
|
7519
7824
|
return model;
|
|
@@ -8319,6 +8624,7 @@ exports.DEFAULT_ROUTER_URL = DEFAULT_ROUTER_URL;
|
|
|
8319
8624
|
exports.DEFAULT_TRACER_OPTIONS = DEFAULT_TRACER_OPTIONS;
|
|
8320
8625
|
exports.Endpoint = Endpoint;
|
|
8321
8626
|
exports.FileTokenStore = FileTokenStore;
|
|
8627
|
+
exports.FlutchChatBedrockConverse = FlutchChatBedrockConverse;
|
|
8322
8628
|
exports.GraphEngineType = GraphEngineType;
|
|
8323
8629
|
exports.GraphManifestSchema = GraphManifestSchema;
|
|
8324
8630
|
exports.GraphManifestValidator = GraphManifestValidator;
|
|
@@ -8331,7 +8637,9 @@ exports.ModelProvider = ModelProvider;
|
|
|
8331
8637
|
exports.ModelType = ModelType;
|
|
8332
8638
|
exports.MongoTokenStore = MongoTokenStore;
|
|
8333
8639
|
exports.OAuthTokenManager = OAuthTokenManager;
|
|
8640
|
+
exports.PROMPT_CACHE_MIN_VERSIONS = PROMPT_CACHE_MIN_VERSIONS;
|
|
8334
8641
|
exports.RetrieverSearchType = RetrieverSearchType;
|
|
8642
|
+
exports.SAMPLING_PARAM_FREE_THRESHOLDS = SAMPLING_PARAM_FREE_THRESHOLDS;
|
|
8335
8643
|
exports.StreamChannel = StreamChannel;
|
|
8336
8644
|
exports.UIEndpoint = UIEndpoint;
|
|
8337
8645
|
exports.UniversalCallbackService = UniversalCallbackService;
|
|
@@ -8341,6 +8649,7 @@ exports.WithEndpoints = WithEndpoints;
|
|
|
8341
8649
|
exports.WithUIEndpoints = WithUIEndpoints;
|
|
8342
8650
|
exports._internals = _internals;
|
|
8343
8651
|
exports.bootstrap = bootstrap;
|
|
8652
|
+
exports.buildEffortRequestFields = buildEffortRequestFields;
|
|
8344
8653
|
exports.buildOAuthAuthorizationUrl = buildOAuthAuthorizationUrl;
|
|
8345
8654
|
exports.buildOpenAIModelConfig = buildOpenAIModelConfig;
|
|
8346
8655
|
exports.clearAttachmentDataStore = clearAttachmentDataStore;
|
|
@@ -8371,15 +8680,24 @@ exports.hasCallbacks = hasCallbacks;
|
|
|
8371
8680
|
exports.hasUIEndpoints = hasUIEndpoints;
|
|
8372
8681
|
exports.hashToolsConfig = hashToolsConfig;
|
|
8373
8682
|
exports.isInternalMode = isInternalMode;
|
|
8683
|
+
exports.isReasoningBlock = isReasoningBlock;
|
|
8374
8684
|
exports.isReasoningModel = isReasoningModel;
|
|
8685
|
+
exports.isSendableReasoningBlock = isSendableReasoningBlock;
|
|
8375
8686
|
exports.loadOAuthProviders = loadOAuthProviders;
|
|
8687
|
+
exports.modelAcceptsSamplingParams = modelAcceptsSamplingParams;
|
|
8688
|
+
exports.modelSupportsPromptCache = modelSupportsPromptCache;
|
|
8376
8689
|
exports.normalizeToolConfigs = normalizeToolConfigs;
|
|
8377
8690
|
exports.registerFinanceExampleCallback = registerFinanceExampleCallback;
|
|
8378
8691
|
exports.registerUIEndpointsFromClass = registerUIEndpointsFromClass;
|
|
8379
8692
|
exports.resolveOAuthProviderConfig = resolveOAuthProviderConfig;
|
|
8693
|
+
exports.resolvePromptCacheControl = resolvePromptCacheControl;
|
|
8380
8694
|
exports.resolveRouterURL = resolveRouterURL;
|
|
8695
|
+
exports.resolveSamplingParams = resolveSamplingParams;
|
|
8696
|
+
exports.sanitizeMessageReasoning = sanitizeMessageReasoning;
|
|
8697
|
+
exports.sanitizeReasoningForBedrock = sanitizeReasoningForBedrock;
|
|
8381
8698
|
exports.sanitizeTraceData = sanitizeTraceData;
|
|
8382
8699
|
exports.storeAttachmentData = storeAttachmentData;
|
|
8700
|
+
exports.toOptionalNumber = toOptionalNumber;
|
|
8383
8701
|
exports.traceApiCall = traceApiCall;
|
|
8384
8702
|
exports.withFlutchContext = withFlutchContext;
|
|
8385
8703
|
exports.wrapCohereFetcher = wrapCohereFetcher;
|