@flutchai/flutch-sdk 0.1.10 → 0.1.12

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 CHANGED
@@ -3909,6 +3909,9 @@ var GraphServiceTokens = {
3909
3909
  CLIENT: "GRAPH_SERVICE_CLIENT",
3910
3910
  SETTINGS_REPOSITORY: "GRAPH_SERVICE_SETTINGS_REPOSITORY"
3911
3911
  };
3912
+
3913
+ // src/graph/graph.controller.ts
3914
+ init_builder_registry_service();
3912
3915
  exports.GraphController = class GraphController {
3913
3916
  constructor(graphService, builderRegistry) {
3914
3917
  this.graphService = graphService;
@@ -4071,7 +4074,8 @@ __decorateClass([
4071
4074
  exports.GraphController = __decorateClass([
4072
4075
  swagger.ApiTags("Graphs"),
4073
4076
  common.Controller(),
4074
- __decorateParam(0, common.Inject("GRAPH_SERVICE"))
4077
+ __decorateParam(0, common.Inject("GRAPH_SERVICE")),
4078
+ __decorateParam(1, common.Inject(exports.BuilderRegistryService))
4075
4079
  ], exports.GraphController);
4076
4080
 
4077
4081
  // src/graph/graph-manifest.schema.ts
@@ -4707,17 +4711,22 @@ exports.EventProcessor = class EventProcessor {
4707
4711
  durationMs: Math.max(0, completedAt - startedAt),
4708
4712
  totalEvents: acc.traceEvents.length
4709
4713
  } : null;
4714
+ const textChain = allChains.find((c) => c.channel === "text");
4715
+ const text = textChain ? textChain.steps.filter((step) => step.type === "text").map((step) => step.text || "").join("") : "";
4710
4716
  this.logger.log("\u{1F4CA} [EventProcessor] Final result assembled", {
4711
4717
  totalChains: allChains.length,
4712
4718
  textChains: allChains.filter((c) => c.channel === "text").length,
4713
4719
  processingChains: allChains.filter((c) => c.channel === "processing").length,
4714
- totalSteps: allChains.reduce((sum, c) => sum + c.steps.length, 0)
4720
+ totalSteps: allChains.reduce((sum, c) => sum + c.steps.length, 0),
4721
+ textLength: text.length
4715
4722
  });
4716
4723
  return {
4717
4724
  content: {
4718
4725
  contentChains: allChains.length > 0 ? allChains : void 0,
4719
4726
  attachments: acc.attachments,
4720
- metadata: acc.metadata
4727
+ metadata: acc.metadata,
4728
+ text
4729
+ // Add extracted text for backwards compatibility
4721
4730
  },
4722
4731
  trace
4723
4732
  };
@@ -5545,37 +5554,43 @@ var McpToolFilter = class _McpToolFilter {
5545
5554
  logger = new common.Logger(_McpToolFilter.name);
5546
5555
  mcpConverter;
5547
5556
  /**
5548
- * Fetch available tools from MCP runtime with optional filtering
5549
- * @param enabledTools Array of tool names to filter for
5550
- * @returns Array of LangChain Tool instances
5557
+ * Fetch available tools from MCP runtime with dynamic schema generation
5558
+ * @param toolsConfig Array of tool configurations with dynamic config
5559
+ * @returns Array of LangChain Tool instances with dynamic schemas
5551
5560
  */
5552
- async getFilteredTools(enabledTools = []) {
5561
+ async getFilteredTools(toolsConfig = []) {
5553
5562
  this.logger.debug(
5554
- `[DEBUG] Getting filtered tools. Enabled: ${enabledTools.join(", ")}`
5563
+ `[DEBUG] Getting filtered tools with dynamic schemas. Config: ${JSON.stringify(toolsConfig)}`
5555
5564
  );
5556
5565
  this.logger.debug(`[DEBUG] MCP Runtime URL: ${this.mcpRuntimeUrl}`);
5557
- if (enabledTools.length === 0) {
5558
- this.logger.debug("No tools enabled, returning empty array");
5566
+ if (toolsConfig.length === 0) {
5567
+ this.logger.debug("No tools configured, returning empty array");
5559
5568
  return [];
5560
5569
  }
5561
5570
  try {
5562
- const filterParam = enabledTools.join(",");
5563
5571
  this.logger.debug(
5564
- `[DEBUG] Making HTTP request to: ${this.mcpRuntimeUrl}/tools/list with filter: ${filterParam}`
5572
+ `[DEBUG] Making HTTP POST request to: ${this.mcpRuntimeUrl}/tools/schemas`
5573
+ );
5574
+ this.logger.debug(`[DEBUG] Request body: ${JSON.stringify(toolsConfig)}`);
5575
+ const response = await axios2__default.default.post(
5576
+ `${this.mcpRuntimeUrl}/tools/schemas`,
5577
+ { tools: toolsConfig },
5578
+ {
5579
+ timeout: 5e3,
5580
+ headers: {
5581
+ "Content-Type": "application/json"
5582
+ }
5583
+ }
5565
5584
  );
5566
- const response = await axios2__default.default.get(`${this.mcpRuntimeUrl}/tools/list`, {
5567
- params: { filter: filterParam },
5568
- timeout: 5e3
5569
- });
5570
5585
  this.logger.debug(
5571
5586
  `[DEBUG] HTTP response status: ${response.status}, data length: ${Array.isArray(response.data) ? response.data.length : "not array"}`
5572
5587
  );
5573
- const filteredTools = Array.isArray(response.data) ? response.data : [];
5588
+ const dynamicTools = Array.isArray(response.data) ? response.data : [];
5574
5589
  this.logger.debug(
5575
- `Retrieved ${filteredTools.length} filtered MCP tools for: ${enabledTools.join(", ")}`
5590
+ `Retrieved ${dynamicTools.length} dynamic tool schemas from MCP Runtime`
5576
5591
  );
5577
5592
  const mcpClient = {
5578
- getTools: async () => filteredTools,
5593
+ getTools: async () => dynamicTools,
5579
5594
  executeTool: async (name, args) => {
5580
5595
  this.logger.debug(`[DEBUG] Executing tool ${name} with args:`, args);
5581
5596
  const response2 = await axios2__default.default.post(
@@ -5590,20 +5605,20 @@ var McpToolFilter = class _McpToolFilter {
5590
5605
  isHealthy: async () => true
5591
5606
  };
5592
5607
  this.logger.log(
5593
- `\u{1F680} [McpToolFilter] Converting ${filteredTools.length} tools using new McpConverter`
5608
+ `\u{1F680} [McpToolFilter] Converting ${dynamicTools.length} dynamic tools using McpConverter`
5594
5609
  );
5595
- const tools = await this.mcpConverter.convertTools(filteredTools);
5610
+ const tools = await this.mcpConverter.convertTools(dynamicTools);
5596
5611
  this.logger.log(
5597
5612
  `\u{1F680} [McpToolFilter] Converted tools: ${tools.map((t) => t.name).join(", ")}`
5598
5613
  );
5599
5614
  this.logger.log(
5600
- `Configured ${tools.length} tools from MCP runtime: ${filteredTools.map((t) => t.name).join(", ")}`
5615
+ `Configured ${tools.length} tools with dynamic schemas from MCP runtime: ${dynamicTools.map((t) => t.name).join(", ")}`
5601
5616
  );
5602
5617
  return tools;
5603
5618
  } catch (error) {
5604
5619
  const errorMessage = error instanceof Error ? error.message : String(error);
5605
5620
  this.logger.warn(
5606
- `[DEBUG] Failed to fetch tools from MCP runtime (${this.mcpRuntimeUrl}): ${errorMessage}`
5621
+ `[DEBUG] Failed to fetch dynamic tool schemas from MCP runtime (${this.mcpRuntimeUrl}): ${errorMessage}`
5607
5622
  );
5608
5623
  this.logger.warn(`[DEBUG] Error details:`, {
5609
5624
  error,
@@ -6148,8 +6163,30 @@ var ModelInitializer = class _ModelInitializer {
6148
6163
  /**
6149
6164
  * Generate cache key for model instances based on configuration
6150
6165
  */
6151
- generateModelCacheKey(modelId, temperature, maxTokens, modelType) {
6152
- return `${modelId}:${temperature || "default"}:${maxTokens || "default"}:${modelType || "chat" /* CHAT */}`;
6166
+ /**
6167
+ * Generate hash from toolsConfig for cache key
6168
+ * Uses MD5 hash to create short, unique identifier
6169
+ */
6170
+ hashToolsConfig(toolsConfig) {
6171
+ const sorted = toolsConfig.map((t) => `${t.toolName}:${t.enabled}:${JSON.stringify(t.config || {})}`).sort().join("|");
6172
+ return crypto.createHash("md5").update(sorted).digest("hex").slice(0, 16);
6173
+ }
6174
+ /**
6175
+ * Generate cache key from ModelByIdConfig
6176
+ * Format: modelId:temperature:maxTokens[:toolsHash]
6177
+ * Example: "model123:0.7:4096" or "model123:0.7:4096:a1b2c3d4e5f6g7h8"
6178
+ */
6179
+ generateModelCacheKey(config) {
6180
+ const parts = [
6181
+ config.modelId,
6182
+ config.temperature ?? "default",
6183
+ config.maxTokens ?? "default"
6184
+ ];
6185
+ if (config.toolsConfig && config.toolsConfig.length > 0) {
6186
+ const toolsHash = this.hashToolsConfig(config.toolsConfig);
6187
+ parts.push(toolsHash);
6188
+ }
6189
+ return parts.join(":");
6153
6190
  }
6154
6191
  /**
6155
6192
  * TEMPORARY SOLUTION for compatibility with new OpenAI models
@@ -6386,12 +6423,7 @@ var ModelInitializer = class _ModelInitializer {
6386
6423
  ["voyageai" /* VOYAGEAI */]: void 0
6387
6424
  };
6388
6425
  async initializeChatModel(config) {
6389
- const cacheKey = this.generateModelCacheKey(
6390
- config.modelId,
6391
- config.temperature,
6392
- config.maxTokens,
6393
- "chat" /* CHAT */
6394
- );
6426
+ const cacheKey = this.generateModelCacheKey(config);
6395
6427
  const cachedModel = this.modelInstanceCache.get(cacheKey);
6396
6428
  if (cachedModel) {
6397
6429
  this.logger.debug(`Using cached chat model instance: ${cacheKey}`);
@@ -6429,17 +6461,76 @@ var ModelInitializer = class _ModelInitializer {
6429
6461
  metadataKeys: Object.keys(model.metadata || {}),
6430
6462
  hasModelId: !!model.metadata?.modelId
6431
6463
  });
6464
+ this.logger.debug(
6465
+ `[TOOLS CHECK] toolsConfig exists: ${!!config.toolsConfig}, customTools exists: ${!!config.customTools}`
6466
+ );
6467
+ if (config.toolsConfig) {
6468
+ this.logger.debug(
6469
+ `[TOOLS CHECK] toolsConfig length: ${config.toolsConfig.length}, content: ${JSON.stringify(config.toolsConfig)}`
6470
+ );
6471
+ }
6472
+ if (config.toolsConfig || config.customTools) {
6473
+ this.logger.debug(
6474
+ `[TOOLS] Calling bindToolsToModel with toolsConfig: ${JSON.stringify(config.toolsConfig)}`
6475
+ );
6476
+ const boundModel = await this.bindToolsToModel(
6477
+ model,
6478
+ config.toolsConfig,
6479
+ config.customTools
6480
+ );
6481
+ this.logger.debug(`[TOOLS] bindToolsToModel returned successfully`);
6482
+ this.modelInstanceCache.set(cacheKey, boundModel);
6483
+ return boundModel;
6484
+ }
6432
6485
  this.modelInstanceCache.set(cacheKey, model);
6433
6486
  return model;
6434
6487
  }
6488
+ /**
6489
+ * Bind tools to model (merge toolsConfig and customTools)
6490
+ * For toolsConfig: fetch tool executors from MCP Runtime
6491
+ * For customTools: use as-is (already prepared DynamicStructuredTool)
6492
+ *
6493
+ * Returns:
6494
+ * - Runnable when tools are bound (model.bindTools returns Runnable)
6495
+ * - BaseChatModel when no tools
6496
+ */
6497
+ async bindToolsToModel(model, toolsConfig, customTools) {
6498
+ const allTools = [];
6499
+ if (toolsConfig && toolsConfig.length > 0) {
6500
+ try {
6501
+ const enabledToolsConfig = toolsConfig.filter(
6502
+ (tc) => tc.enabled !== false
6503
+ );
6504
+ if (enabledToolsConfig.length > 0) {
6505
+ this.logger.debug(
6506
+ `Fetching ${enabledToolsConfig.length} tools with dynamic schemas from MCP Runtime: ${enabledToolsConfig.map((tc) => tc.toolName).join(", ")}`
6507
+ );
6508
+ const mcpToolFilter = new McpToolFilter();
6509
+ const mcpTools = await mcpToolFilter.getFilteredTools(enabledToolsConfig);
6510
+ this.logger.debug(
6511
+ `Successfully fetched ${mcpTools.length} tools with dynamic schemas from MCP Runtime`
6512
+ );
6513
+ allTools.push(...mcpTools);
6514
+ }
6515
+ } catch (error) {
6516
+ this.logger.error(
6517
+ `Failed to fetch tools from MCP Runtime: ${error instanceof Error ? error.message : String(error)}`
6518
+ );
6519
+ }
6520
+ }
6521
+ if (customTools && customTools.length > 0) {
6522
+ allTools.push(...customTools);
6523
+ this.logger.debug(`Added ${customTools.length} custom tools to model`);
6524
+ }
6525
+ if (allTools.length > 0) {
6526
+ this.logger.debug(`Binding ${allTools.length} tools to model`);
6527
+ const modelWithTools = model.bindTools(allTools);
6528
+ return modelWithTools;
6529
+ }
6530
+ return model;
6531
+ }
6435
6532
  async initializeRerankModel(config) {
6436
- const cacheKey = this.generateModelCacheKey(
6437
- config.modelId,
6438
- void 0,
6439
- // rerank models typically don't use temperature
6440
- config.maxTokens,
6441
- "rerank" /* RERANK */
6442
- );
6533
+ const cacheKey = this.generateModelCacheKey(config);
6443
6534
  const cachedModel = this.modelInstanceCache.get(cacheKey);
6444
6535
  if (cachedModel) {
6445
6536
  this.logger.debug(`Using cached rerank model instance: ${cacheKey}`);
@@ -6467,14 +6558,7 @@ var ModelInitializer = class _ModelInitializer {
6467
6558
  return model;
6468
6559
  }
6469
6560
  async initializeEmbeddingModel(config) {
6470
- const cacheKey = this.generateModelCacheKey(
6471
- config.modelId,
6472
- void 0,
6473
- // embedding models typically don't use temperature
6474
- void 0,
6475
- // embedding models typically don't use maxTokens
6476
- "embedding" /* EMBEDDING */
6477
- );
6561
+ const cacheKey = this.generateModelCacheKey(config);
6478
6562
  const cachedModel = this.modelInstanceCache.get(cacheKey);
6479
6563
  if (cachedModel) {
6480
6564
  this.logger.debug(`Using cached embedding model instance: ${cacheKey}`);
@@ -6622,7 +6706,7 @@ var ModelInitializer = class _ModelInitializer {
6622
6706
  }
6623
6707
  // Simple API request for microservices (copy from original LLMInitializer)
6624
6708
  async fetchFromApi(modelId) {
6625
- const apiUrl = process.env.API_URL || "http://amelie-service";
6709
+ const apiUrl = process.env.API_URL;
6626
6710
  const token = process.env.INTERNAL_API_TOKEN;
6627
6711
  if (!token) {
6628
6712
  throw new Error("INTERNAL_API_TOKEN required for API mode");
@@ -6666,40 +6750,6 @@ var ModelInitializer = class _ModelInitializer {
6666
6750
  return result;
6667
6751
  }
6668
6752
  };
6669
- function prepareModelWithTools(model, tools, baseConfig = {}) {
6670
- if (tools.length === 0) {
6671
- return {
6672
- modelWithTools: model,
6673
- finalConfig: baseConfig,
6674
- toolsMethod: "none"
6675
- };
6676
- }
6677
- if (model.bindTools && typeof model.bindTools === "function") {
6678
- try {
6679
- const modelWithTools = model.bindTools(tools);
6680
- return {
6681
- modelWithTools,
6682
- finalConfig: baseConfig,
6683
- toolsMethod: "bindTools"
6684
- };
6685
- } catch (error) {
6686
- const invokeConfig2 = { tools };
6687
- const finalConfig2 = { ...baseConfig, ...invokeConfig2 };
6688
- return {
6689
- modelWithTools: model,
6690
- finalConfig: finalConfig2,
6691
- toolsMethod: "manual"
6692
- };
6693
- }
6694
- }
6695
- const invokeConfig = { tools };
6696
- const finalConfig = { ...baseConfig, ...invokeConfig };
6697
- return {
6698
- modelWithTools: model,
6699
- finalConfig,
6700
- toolsMethod: "manual"
6701
- };
6702
- }
6703
6753
 
6704
6754
  // src/retriever/enums.ts
6705
6755
  var RetrieverSearchType = /* @__PURE__ */ ((RetrieverSearchType2) => {
@@ -7049,7 +7099,6 @@ exports.getUIEndpointClassMetadata = getUIEndpointClassMetadata;
7049
7099
  exports.getUIEndpointMethodsMetadata = getUIEndpointMethodsMetadata;
7050
7100
  exports.hasCallbacks = hasCallbacks;
7051
7101
  exports.hasUIEndpoints = hasUIEndpoints;
7052
- exports.prepareModelWithTools = prepareModelWithTools;
7053
7102
  exports.registerFinanceExampleCallback = registerFinanceExampleCallback;
7054
7103
  exports.registerUIEndpointsFromClass = registerUIEndpointsFromClass;
7055
7104
  exports.sanitizeTraceData = sanitizeTraceData;