@flutchai/flutch-sdk 0.1.8 → 0.1.9
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 +196 -93
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -13
- package/dist/index.d.ts +5 -13
- package/dist/index.js +196 -93
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -15,6 +15,7 @@ var LangGraph = require('@langchain/langgraph');
|
|
|
15
15
|
var tools = require('@langchain/core/tools');
|
|
16
16
|
var zod = require('zod');
|
|
17
17
|
var axios2 = require('axios');
|
|
18
|
+
var manager = require('@langchain/core/callbacks/manager');
|
|
18
19
|
var openai = require('@langchain/openai');
|
|
19
20
|
var azureOpenai = require('@langchain/azure-openai');
|
|
20
21
|
var anthropic = require('@langchain/anthropic');
|
|
@@ -4330,7 +4331,7 @@ function sanitizeTraceData(value, depth = 0, seen = /* @__PURE__ */ new WeakSet(
|
|
|
4330
4331
|
return null;
|
|
4331
4332
|
}
|
|
4332
4333
|
if (typeof value === "string") {
|
|
4333
|
-
return value
|
|
4334
|
+
return value;
|
|
4334
4335
|
}
|
|
4335
4336
|
if (typeof value === "number" || typeof value === "boolean") {
|
|
4336
4337
|
return value;
|
|
@@ -4586,6 +4587,31 @@ exports.EventProcessor = class EventProcessor {
|
|
|
4586
4587
|
}
|
|
4587
4588
|
return;
|
|
4588
4589
|
}
|
|
4590
|
+
if (event.event === "on_tool_start") {
|
|
4591
|
+
this.logger.log("\u{1F527} Tool execution started", {
|
|
4592
|
+
toolName: event.name,
|
|
4593
|
+
input: event.data?.input,
|
|
4594
|
+
runId: event.run_id,
|
|
4595
|
+
metadata: event.metadata
|
|
4596
|
+
});
|
|
4597
|
+
return;
|
|
4598
|
+
}
|
|
4599
|
+
if (event.event === "on_tool_end") {
|
|
4600
|
+
this.logger.log("\u2705 Tool execution completed", {
|
|
4601
|
+
toolName: event.name,
|
|
4602
|
+
output: typeof event.data?.output === "string" ? event.data.output.substring(0, 200) + (event.data.output.length > 200 ? "..." : "") : event.data?.output,
|
|
4603
|
+
runId: event.run_id
|
|
4604
|
+
});
|
|
4605
|
+
return;
|
|
4606
|
+
}
|
|
4607
|
+
if (event.event === "on_tool_error") {
|
|
4608
|
+
this.logger.error("\u274C Tool execution failed", {
|
|
4609
|
+
toolName: event.name,
|
|
4610
|
+
error: event.data?.error,
|
|
4611
|
+
runId: event.run_id
|
|
4612
|
+
});
|
|
4613
|
+
return;
|
|
4614
|
+
}
|
|
4589
4615
|
if (event.event === "on_chat_model_end") {
|
|
4590
4616
|
const output = event.data?.output;
|
|
4591
4617
|
const usageMetadata = output?.usage_metadata || output?.usageMetadata;
|
|
@@ -4711,42 +4737,9 @@ exports.EventProcessor = class EventProcessor {
|
|
|
4711
4737
|
/**
|
|
4712
4738
|
* Build final result from accumulator
|
|
4713
4739
|
* Uses generation if available, otherwise falls back to streamed text
|
|
4714
|
-
* Returns content and
|
|
4740
|
+
* Returns content and trace events (metrics should be extracted from trace on backend)
|
|
4715
4741
|
*/
|
|
4716
4742
|
getResult(acc) {
|
|
4717
|
-
const totalPromptTokens = acc.llmCalls.reduce(
|
|
4718
|
-
(sum, call) => sum + call.promptTokens,
|
|
4719
|
-
0
|
|
4720
|
-
);
|
|
4721
|
-
const totalCompletionTokens = acc.llmCalls.reduce(
|
|
4722
|
-
(sum, call) => sum + call.completionTokens,
|
|
4723
|
-
0
|
|
4724
|
-
);
|
|
4725
|
-
const totalTokens = acc.llmCalls.reduce(
|
|
4726
|
-
(sum, call) => sum + call.totalTokens,
|
|
4727
|
-
0
|
|
4728
|
-
);
|
|
4729
|
-
this.logger.log("\u{1F4CA} Final metrics collected", {
|
|
4730
|
-
llmCallsCount: acc.llmCalls.length,
|
|
4731
|
-
totalPromptTokens,
|
|
4732
|
-
totalCompletionTokens,
|
|
4733
|
-
totalTokens,
|
|
4734
|
-
modelIds: acc.llmCalls.map((c) => c.modelId)
|
|
4735
|
-
});
|
|
4736
|
-
const metrics = acc.llmCalls.length > 0 ? {
|
|
4737
|
-
modelCalls: acc.llmCalls.map((call) => ({
|
|
4738
|
-
nodeName: call.nodeName || "unknown",
|
|
4739
|
-
timestamp: call.timestamp,
|
|
4740
|
-
modelId: call.modelId,
|
|
4741
|
-
promptTokens: call.promptTokens,
|
|
4742
|
-
completionTokens: call.completionTokens,
|
|
4743
|
-
totalTokens: call.totalTokens,
|
|
4744
|
-
latencyMs: 0
|
|
4745
|
-
// Not calculated from events
|
|
4746
|
-
})),
|
|
4747
|
-
apiCalls: []
|
|
4748
|
-
// TODO: Add API calls tracking (rerank, embeddings) via custom events
|
|
4749
|
-
} : null;
|
|
4750
4743
|
const startedAt = acc.traceStartedAt ?? Date.now();
|
|
4751
4744
|
const completedAt = acc.traceCompletedAt ?? startedAt;
|
|
4752
4745
|
const trace = acc.traceEvents.length > 0 ? {
|
|
@@ -4775,7 +4768,6 @@ exports.EventProcessor = class EventProcessor {
|
|
|
4775
4768
|
metadata: acc.generation?.metadata || {},
|
|
4776
4769
|
reasoningChains: acc.reasoningChains.length > 0 ? acc.reasoningChains : void 0
|
|
4777
4770
|
},
|
|
4778
|
-
metrics,
|
|
4779
4771
|
trace
|
|
4780
4772
|
};
|
|
4781
4773
|
}
|
|
@@ -4890,33 +4882,14 @@ exports.LangGraphEngine = class LangGraphEngine {
|
|
|
4890
4882
|
);
|
|
4891
4883
|
}
|
|
4892
4884
|
}
|
|
4893
|
-
const { content,
|
|
4885
|
+
const { content, trace } = this.eventProcessor.getResult(acc);
|
|
4894
4886
|
this.logger.debug("[STREAM-RESULT] Got result from EventProcessor", {
|
|
4895
4887
|
hasContent: !!content,
|
|
4896
|
-
hasMetrics: !!metrics,
|
|
4897
|
-
modelCallsCount: metrics?.modelCalls?.length || 0,
|
|
4898
|
-
apiCallsCount: metrics?.apiCalls?.length || 0,
|
|
4899
4888
|
hasContext: !!config.configurable?.context,
|
|
4900
4889
|
hasTrace: !!trace,
|
|
4901
|
-
traceEvents: trace?.events?.length || 0
|
|
4890
|
+
traceEvents: trace?.events?.length || 0,
|
|
4891
|
+
totalModelCalls: trace?.totalModelCalls || 0
|
|
4902
4892
|
});
|
|
4903
|
-
if (metrics && metrics.modelCalls?.length > 0 && config.configurable?.context) {
|
|
4904
|
-
const context = config.configurable.context;
|
|
4905
|
-
await this.sendMetricsWebhook({
|
|
4906
|
-
messageId: context.messageId || "unknown",
|
|
4907
|
-
threadId: context.threadId || "unknown",
|
|
4908
|
-
userId: context.userId || "unknown",
|
|
4909
|
-
agentId: context.agentId || "unknown",
|
|
4910
|
-
companyId: context.companyId || "unknown",
|
|
4911
|
-
metrics
|
|
4912
|
-
});
|
|
4913
|
-
} else {
|
|
4914
|
-
this.logger.debug("[METRICS-WEBHOOK] Skipping webhook", {
|
|
4915
|
-
hasMetrics: !!metrics,
|
|
4916
|
-
modelCallsCount: metrics?.modelCalls?.length || 0,
|
|
4917
|
-
hasContext: !!config.configurable?.context
|
|
4918
|
-
});
|
|
4919
|
-
}
|
|
4920
4893
|
if (trace && trace.events.length > 0 && config.configurable?.context) {
|
|
4921
4894
|
const context = config.configurable.context;
|
|
4922
4895
|
this.logger.debug("[TRACE-WEBHOOK] Sending trace events batch", {
|
|
@@ -5396,47 +5369,65 @@ var McpConverter = class _McpConverter {
|
|
|
5396
5369
|
mcpRuntimeUrl;
|
|
5397
5370
|
constructor(mcpRuntimeUrl = "http://localhost:3004") {
|
|
5398
5371
|
this.mcpRuntimeUrl = mcpRuntimeUrl;
|
|
5372
|
+
this.logger.log(
|
|
5373
|
+
`\u{1F527} McpConverter initialized with SDK version 0.1.8 (manual jsonSchemaToZod)`
|
|
5374
|
+
);
|
|
5399
5375
|
}
|
|
5400
5376
|
/**
|
|
5401
|
-
* Convert JSON Schema to
|
|
5377
|
+
* Convert JSON Schema to Zod schema manually
|
|
5378
|
+
* This creates a standard Zod schema that zodToJsonSchema can convert back properly
|
|
5402
5379
|
*/
|
|
5403
5380
|
jsonSchemaToZod(jsonSchema) {
|
|
5404
5381
|
if (!jsonSchema || typeof jsonSchema !== "object") {
|
|
5405
5382
|
return zod.z.any();
|
|
5406
5383
|
}
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5384
|
+
try {
|
|
5385
|
+
if (jsonSchema.type === "object" && jsonSchema.properties) {
|
|
5386
|
+
const shape = {};
|
|
5387
|
+
for (const [key, propSchema] of Object.entries(jsonSchema.properties)) {
|
|
5388
|
+
const prop = propSchema;
|
|
5389
|
+
let zodProp;
|
|
5390
|
+
switch (prop.type) {
|
|
5391
|
+
case "string":
|
|
5392
|
+
zodProp = zod.z.string();
|
|
5393
|
+
break;
|
|
5394
|
+
case "number":
|
|
5395
|
+
zodProp = zod.z.number();
|
|
5396
|
+
break;
|
|
5397
|
+
case "boolean":
|
|
5398
|
+
zodProp = zod.z.boolean();
|
|
5399
|
+
break;
|
|
5400
|
+
case "integer":
|
|
5401
|
+
zodProp = zod.z.number().int();
|
|
5402
|
+
break;
|
|
5403
|
+
case "array":
|
|
5404
|
+
zodProp = zod.z.array(zod.z.any());
|
|
5405
|
+
break;
|
|
5406
|
+
case "object":
|
|
5407
|
+
zodProp = zod.z.record(zod.z.any());
|
|
5408
|
+
break;
|
|
5409
|
+
default:
|
|
5410
|
+
zodProp = zod.z.any();
|
|
5411
|
+
}
|
|
5412
|
+
if (prop.description) {
|
|
5413
|
+
zodProp = zodProp.describe(prop.description);
|
|
5414
|
+
}
|
|
5415
|
+
if (!jsonSchema.required?.includes(key)) {
|
|
5416
|
+
zodProp = zodProp.optional();
|
|
5417
|
+
}
|
|
5418
|
+
shape[key] = zodProp;
|
|
5419
|
+
}
|
|
5420
|
+
return zod.z.object(shape);
|
|
5421
|
+
}
|
|
5422
|
+
this.logger.warn(
|
|
5423
|
+
`Unsupported JSON Schema structure, falling back to z.any()`
|
|
5424
|
+
);
|
|
5425
|
+
return zod.z.any();
|
|
5426
|
+
} catch (error) {
|
|
5427
|
+
this.logger.warn(
|
|
5428
|
+
`Failed to convert JSON Schema, falling back to z.any(): ${error}`
|
|
5429
|
+
);
|
|
5430
|
+
return zod.z.any();
|
|
5440
5431
|
}
|
|
5441
5432
|
}
|
|
5442
5433
|
/**
|
|
@@ -5445,6 +5436,27 @@ var McpConverter = class _McpConverter {
|
|
|
5445
5436
|
convertTool(mcpTool) {
|
|
5446
5437
|
const logger2 = this.logger;
|
|
5447
5438
|
const mcpRuntimeUrl = this.mcpRuntimeUrl;
|
|
5439
|
+
let enhancedDescription = mcpTool.description;
|
|
5440
|
+
if (mcpTool.inputSchema?.properties) {
|
|
5441
|
+
const paramDescriptions = [];
|
|
5442
|
+
for (const [key, propSchema] of Object.entries(
|
|
5443
|
+
mcpTool.inputSchema.properties
|
|
5444
|
+
)) {
|
|
5445
|
+
const prop = propSchema;
|
|
5446
|
+
if (prop.description) {
|
|
5447
|
+
const isRequired = mcpTool.inputSchema.required?.includes(key);
|
|
5448
|
+
paramDescriptions.push(
|
|
5449
|
+
`- ${key}${isRequired ? " (required)" : ""}: ${prop.description}`
|
|
5450
|
+
);
|
|
5451
|
+
}
|
|
5452
|
+
}
|
|
5453
|
+
if (paramDescriptions.length > 0) {
|
|
5454
|
+
enhancedDescription = `${mcpTool.description}
|
|
5455
|
+
|
|
5456
|
+
Parameters:
|
|
5457
|
+
${paramDescriptions.join("\n")}`;
|
|
5458
|
+
}
|
|
5459
|
+
}
|
|
5448
5460
|
const schema = this.jsonSchemaToZod(mcpTool.inputSchema);
|
|
5449
5461
|
logger2.debug(
|
|
5450
5462
|
`\u{1F527} [${mcpTool.name}] Original schema:`,
|
|
@@ -5453,9 +5465,48 @@ var McpConverter = class _McpConverter {
|
|
|
5453
5465
|
logger2.debug(
|
|
5454
5466
|
`\u{1F527} [${mcpTool.name}] Using schema type: ${schema?._def?.typeName ?? "unknown"}`
|
|
5455
5467
|
);
|
|
5468
|
+
if (schema?._def?.shape && typeof schema._def.shape === "function") {
|
|
5469
|
+
try {
|
|
5470
|
+
const shape = schema._def.shape();
|
|
5471
|
+
logger2.debug(
|
|
5472
|
+
`\u{1F527} [${mcpTool.name}] Converted Zod schema shape:`,
|
|
5473
|
+
JSON.stringify(
|
|
5474
|
+
Object.entries(shape).reduce(
|
|
5475
|
+
(acc, [key, val]) => {
|
|
5476
|
+
acc[key] = {
|
|
5477
|
+
type: val?._def?.typeName,
|
|
5478
|
+
description: val?._def?.description,
|
|
5479
|
+
optional: val?._def?.typeName === "ZodOptional"
|
|
5480
|
+
};
|
|
5481
|
+
return acc;
|
|
5482
|
+
},
|
|
5483
|
+
{}
|
|
5484
|
+
),
|
|
5485
|
+
null,
|
|
5486
|
+
2
|
|
5487
|
+
)
|
|
5488
|
+
);
|
|
5489
|
+
} catch (error) {
|
|
5490
|
+
logger2.debug(
|
|
5491
|
+
`\u{1F527} [${mcpTool.name}] Could not extract Zod schema shape: ${error}`
|
|
5492
|
+
);
|
|
5493
|
+
}
|
|
5494
|
+
}
|
|
5495
|
+
try {
|
|
5496
|
+
const { zodToJsonSchema } = __require("zod-to-json-schema");
|
|
5497
|
+
const convertedJsonSchema = zodToJsonSchema(schema);
|
|
5498
|
+
logger2.warn(
|
|
5499
|
+
`\u{1F527} [${mcpTool.name}] JSON Schema that LangChain will use:`,
|
|
5500
|
+
JSON.stringify(convertedJsonSchema, null, 2)
|
|
5501
|
+
);
|
|
5502
|
+
} catch (error) {
|
|
5503
|
+
logger2.warn(
|
|
5504
|
+
`\u{1F527} [${mcpTool.name}] Could not convert Zod to JSON Schema: ${error}`
|
|
5505
|
+
);
|
|
5506
|
+
}
|
|
5456
5507
|
return new tools.DynamicStructuredTool({
|
|
5457
5508
|
name: mcpTool.name,
|
|
5458
|
-
description:
|
|
5509
|
+
description: enhancedDescription,
|
|
5459
5510
|
schema,
|
|
5460
5511
|
func: async (input) => {
|
|
5461
5512
|
logger2.log(`\u{1F527} [${mcpTool.name}] LLM INPUT: ${JSON.stringify(input)}`);
|
|
@@ -5772,6 +5823,58 @@ exports.McpRuntimeHttpClient = class McpRuntimeHttpClient {
|
|
|
5772
5823
|
return false;
|
|
5773
5824
|
}
|
|
5774
5825
|
}
|
|
5826
|
+
/**
|
|
5827
|
+
* Execute tool with LangChain event emission
|
|
5828
|
+
* @param toolCallId - Tool call ID from LLM
|
|
5829
|
+
* @param toolName - Tool name
|
|
5830
|
+
* @param enrichedArgs - Merged arguments (toolConfig + LLM args)
|
|
5831
|
+
* @param executionContext - Execution context (userId, agentId, etc.)
|
|
5832
|
+
* @param config - RunnableConfig with callbacks
|
|
5833
|
+
* @returns Tool execution result with content
|
|
5834
|
+
*/
|
|
5835
|
+
async executeToolWithEvents(toolCallId, toolName, enrichedArgs, executionContext, config) {
|
|
5836
|
+
const parsedConfig = manager.parseCallbackConfigArg(config);
|
|
5837
|
+
const callbackManager = manager.CallbackManager.configure(parsedConfig.callbacks);
|
|
5838
|
+
let runManager;
|
|
5839
|
+
try {
|
|
5840
|
+
runManager = await callbackManager?.handleToolStart(
|
|
5841
|
+
{
|
|
5842
|
+
name: toolName,
|
|
5843
|
+
lc: 1,
|
|
5844
|
+
type: "not_implemented",
|
|
5845
|
+
id: ["langchain", "tools", "mcp", toolName]
|
|
5846
|
+
},
|
|
5847
|
+
JSON.stringify(enrichedArgs),
|
|
5848
|
+
parsedConfig.runId,
|
|
5849
|
+
void 0,
|
|
5850
|
+
parsedConfig.tags,
|
|
5851
|
+
parsedConfig.metadata,
|
|
5852
|
+
toolName
|
|
5853
|
+
);
|
|
5854
|
+
const result = await this.executeTool(
|
|
5855
|
+
toolName,
|
|
5856
|
+
enrichedArgs,
|
|
5857
|
+
executionContext
|
|
5858
|
+
);
|
|
5859
|
+
const content = result.success ? JSON.stringify(result) : result.error || JSON.stringify(result);
|
|
5860
|
+
await runManager?.handleToolEnd(content);
|
|
5861
|
+
return {
|
|
5862
|
+
content,
|
|
5863
|
+
success: result.success
|
|
5864
|
+
};
|
|
5865
|
+
} catch (error) {
|
|
5866
|
+
this.logger.error(`Error executing tool ${toolName}:`, error);
|
|
5867
|
+
await runManager?.handleToolError(error);
|
|
5868
|
+
const errorContent = JSON.stringify({
|
|
5869
|
+
success: false,
|
|
5870
|
+
error: error instanceof Error ? error.message : "Tool execution failed"
|
|
5871
|
+
});
|
|
5872
|
+
return {
|
|
5873
|
+
content: errorContent,
|
|
5874
|
+
success: false
|
|
5875
|
+
};
|
|
5876
|
+
}
|
|
5877
|
+
}
|
|
5775
5878
|
};
|
|
5776
5879
|
exports.McpRuntimeHttpClient = __decorateClass([
|
|
5777
5880
|
common.Injectable()
|