@flutchai/flutch-sdk 0.2.1 → 0.2.2

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
@@ -1323,34 +1323,25 @@ exports.AbstractGraphBuilder = class AbstractGraphBuilder {
1323
1323
  }
1324
1324
  }
1325
1325
  /**
1326
- * Creates execution context for graph with tracer and usageRecorder
1327
- * This method can be overridden in child classes for customization
1326
+ * Prepare config for graph execution
1327
+ * Config comes ready from backend, just add input
1328
1328
  */
1329
- createGraphContext(payload) {
1330
- return {
1331
- messageId: payload.messageId,
1332
- threadId: payload.threadId,
1333
- userId: payload.userId,
1334
- agentId: payload.agentId,
1335
- companyId: payload.companyId
1336
- };
1329
+ async preparePayload(payload) {
1330
+ const config = await this.prepareConfig(payload);
1331
+ return config;
1337
1332
  }
1338
1333
  /**
1339
- * Basic configuration preparation for graph execution
1340
- * Automatically creates context with tracer and usageRecorder
1341
- * Handles message deserialization and LangGraph-compatible structure
1342
- * FINAL method - cannot be overridden. Use customizeConfig() hook instead.
1334
+ * Internal method to prepare config with input deserialization
1343
1335
  */
1344
1336
  async prepareConfig(payload) {
1345
- const context = this.createGraphContext(payload);
1346
- let message = payload.message;
1347
- if (payload.message && typeof payload.message === "object" && "lc" in payload.message) {
1337
+ let input = payload.input;
1338
+ if (payload.input && typeof payload.input === "object" && "lc" in payload.input) {
1348
1339
  try {
1349
1340
  const { load } = await import('@langchain/core/load');
1350
- message = await load(JSON.stringify(payload.message));
1341
+ input = await load(JSON.stringify(payload.input));
1351
1342
  this.logger.debug({
1352
1343
  message: "Deserialized BaseMessage using load()",
1353
- type: message.constructor?.name
1344
+ type: input.constructor?.name
1354
1345
  });
1355
1346
  } catch (error) {
1356
1347
  this.logger.warn({
@@ -1360,28 +1351,8 @@ exports.AbstractGraphBuilder = class AbstractGraphBuilder {
1360
1351
  }
1361
1352
  }
1362
1353
  const baseConfig = {
1363
- // Input for LangGraph (messages array)
1364
- input: message ? {
1365
- messages: [message]
1366
- } : void 0,
1367
- // Configurable settings for LangGraph checkpointing and context
1368
- configurable: {
1369
- thread_id: payload.threadId,
1370
- checkpoint_ns: this.graphType,
1371
- checkpoint_id: `${payload.threadId}-${Date.now()}`,
1372
- context,
1373
- // Add metadata for compatibility
1374
- metadata: {
1375
- userId: payload.userId,
1376
- agentId: payload.agentId,
1377
- requestId: payload.requestId,
1378
- graphType: this.graphType,
1379
- version: this.version,
1380
- workflowType: this.graphType
1381
- },
1382
- // Graph-specific settings from payload
1383
- graphSettings: payload.graphSettings || {}
1384
- }
1354
+ ...payload.config,
1355
+ input
1385
1356
  };
1386
1357
  const finalConfig = await this.customizeConfig(baseConfig, payload);
1387
1358
  return finalConfig;
@@ -1564,9 +1535,15 @@ exports.UniversalGraphService = class UniversalGraphService {
1564
1535
  * Generate answer without streaming
1565
1536
  */
1566
1537
  async generateAnswer(payload) {
1567
- const builder = this.getBuilderForType(payload.graphType);
1538
+ const graphType = payload.config?.configurable?.graphSettings?.graphType;
1539
+ if (!graphType) {
1540
+ throw new Error(
1541
+ "GraphType is required in payload.config.configurable.graphSettings"
1542
+ );
1543
+ }
1544
+ const builder = this.getBuilderForType(graphType);
1568
1545
  const graph = await builder.buildGraph(payload);
1569
- const config = await builder.prepareConfig(payload);
1546
+ const config = await builder.preparePayload(payload);
1570
1547
  const abortController = new AbortController();
1571
1548
  this.registerActiveGeneration(payload.requestId, () => {
1572
1549
  abortController.abort();
@@ -1598,13 +1575,16 @@ exports.UniversalGraphService = class UniversalGraphService {
1598
1575
  );
1599
1576
  const abortController = new AbortController();
1600
1577
  try {
1601
- const builder = this.getBuilderForType(payload.graphType);
1602
- this.logger.debug(`Got builder for graph type: ${payload.graphType}`);
1578
+ const graphType = payload.config?.configurable?.graphSettings?.graphType;
1579
+ if (!graphType) {
1580
+ throw new Error(
1581
+ "GraphType is required in payload.config.configurable.graphSettings"
1582
+ );
1583
+ }
1584
+ const builder = this.getBuilderForType(graphType);
1585
+ this.logger.debug(`Got builder for graph type: ${graphType}`);
1603
1586
  const graph = await builder.buildGraph(payload);
1604
- this.logger.debug(`Graph built for requestId: ${payload.requestId}`);
1605
- this.logger.debug(`Preparing config for requestId: ${payload.requestId}`);
1606
- const config = await builder.prepareConfig(payload);
1607
- this.logger.debug(`Config prepared`);
1587
+ const graphRequest = await builder.preparePayload(payload);
1608
1588
  this.registerActiveGeneration(payload.requestId, () => {
1609
1589
  abortController.abort();
1610
1590
  });
@@ -1614,7 +1594,7 @@ exports.UniversalGraphService = class UniversalGraphService {
1614
1594
  );
1615
1595
  const result = await this.engine.streamGraph(
1616
1596
  graph,
1617
- config,
1597
+ graphRequest,
1618
1598
  onPartial,
1619
1599
  abortController.signal
1620
1600
  );
@@ -5016,6 +4996,43 @@ exports.LangGraphEngine = class LangGraphEngine {
5016
4996
  }
5017
4997
  }
5018
4998
  logger = new common.Logger(exports.LangGraphEngine.name);
4999
+ /**
5000
+ * Deserialize input recursively
5001
+ * Handles serialized LangChain objects at any level of nesting
5002
+ */
5003
+ async deserializeInput(input) {
5004
+ const { load } = await import('@langchain/core/load');
5005
+ const deserializeValue = async (value) => {
5006
+ if (value && typeof value === "object" && "lc" in value) {
5007
+ try {
5008
+ const deserialized = await load(JSON.stringify(value));
5009
+ this.logger.debug({
5010
+ message: "Deserialized LangChain object",
5011
+ type: deserialized.constructor?.name
5012
+ });
5013
+ return deserialized;
5014
+ } catch (error) {
5015
+ this.logger.warn({
5016
+ message: "Failed to deserialize LangChain object",
5017
+ error: error.message
5018
+ });
5019
+ return value;
5020
+ }
5021
+ }
5022
+ if (Array.isArray(value)) {
5023
+ return await Promise.all(value.map((item) => deserializeValue(item)));
5024
+ }
5025
+ if (value && typeof value === "object" && value.constructor === Object) {
5026
+ const result = {};
5027
+ for (const [key, val] of Object.entries(value)) {
5028
+ result[key] = await deserializeValue(val);
5029
+ }
5030
+ return result;
5031
+ }
5032
+ return value;
5033
+ };
5034
+ return await deserializeValue(input);
5035
+ }
5019
5036
  /**
5020
5037
  * Method to invoke LangGraph
5021
5038
  */
@@ -5023,23 +5040,41 @@ exports.LangGraphEngine = class LangGraphEngine {
5023
5040
  if (signal) {
5024
5041
  config.signal = signal;
5025
5042
  }
5043
+ const input = await this.deserializeInput(config.input || {});
5026
5044
  const recursionLimit = config.recursionLimit ?? DEFAULT_RECURSION_LIMIT;
5027
- const result = await graph.invoke(config.input || {}, {
5045
+ const result = await graph.invoke(input, {
5028
5046
  ...config,
5029
5047
  recursionLimit
5030
5048
  });
5031
5049
  return this.processGraphResult(result);
5032
5050
  }
5033
- async streamGraph(graph, config, onPartial, signal) {
5051
+ async streamGraph(graph, preparedPayload, onPartial, signal) {
5034
5052
  const acc = this.eventProcessor.createAccumulator();
5035
5053
  let streamError = null;
5054
+ this.logger.debug({
5055
+ message: "[ENGINE] streamGraph called",
5056
+ hasSignal: !!signal,
5057
+ signalType: signal?.constructor?.name,
5058
+ hasAborted: signal?.aborted
5059
+ });
5036
5060
  try {
5037
5061
  if (signal) {
5038
- config.signal = signal;
5039
- }
5040
- const recursionLimit = config.recursionLimit ?? DEFAULT_RECURSION_LIMIT;
5041
- const eventStream = await graph.streamEvents(config.input || {}, {
5042
- ...config,
5062
+ preparedPayload.signal = signal;
5063
+ this.logger.debug("[ENGINE] Signal assigned to preparedPayload.signal");
5064
+ }
5065
+ const input = await this.deserializeInput(preparedPayload.input || {});
5066
+ const recursionLimit = preparedPayload.recursionLimit ?? DEFAULT_RECURSION_LIMIT;
5067
+ this.logger.debug({
5068
+ message: "[ENGINE] Calling streamEvents",
5069
+ hasSignalInPayload: !!preparedPayload.signal,
5070
+ signalAborted: preparedPayload.signal?.aborted,
5071
+ configKeys: Object.keys(preparedPayload.config || {}),
5072
+ hasSignalInConfig: !!preparedPayload.config?.signal
5073
+ });
5074
+ const eventStream = await graph.streamEvents(input, {
5075
+ ...preparedPayload.config,
5076
+ signal: preparedPayload.signal,
5077
+ // Include abort signal
5043
5078
  version: "v2",
5044
5079
  // Important for correct operation
5045
5080
  recursionLimit
@@ -5061,12 +5096,12 @@ exports.LangGraphEngine = class LangGraphEngine {
5061
5096
  );
5062
5097
  this.logger.error(`[STREAM-ERROR] Stack trace: ${streamError.stack}`);
5063
5098
  } finally {
5064
- await this.sendTraceFromAccumulator(acc, config, streamError);
5099
+ await this.sendTraceFromAccumulator(acc, preparedPayload, streamError);
5065
5100
  }
5066
5101
  const { content, trace } = this.eventProcessor.getResult(acc);
5067
5102
  this.logger.debug("[STREAM-RESULT] Got result from EventProcessor", {
5068
5103
  hasContent: !!content,
5069
- hasContext: !!config.configurable?.context,
5104
+ hasContext: !!preparedPayload.configurable?.context,
5070
5105
  hasTrace: !!trace,
5071
5106
  traceEvents: trace?.events?.length || 0,
5072
5107
  hadError: !!streamError
@@ -5279,9 +5314,11 @@ function createMetaBuilder(config, versionedGraphService, moduleRef) {
5279
5314
  return config.baseGraphType;
5280
5315
  }
5281
5316
  async buildGraph(payload) {
5282
- const graphType = payload.graphSettings?.graphType;
5317
+ const graphType = payload.config?.configurable?.graphSettings?.graphType;
5283
5318
  if (!graphType) {
5284
- throw new Error("GraphType is required in payload.graphSettings");
5319
+ throw new Error(
5320
+ "GraphType is required in payload.config.configurable.graphSettings"
5321
+ );
5285
5322
  }
5286
5323
  const resolution = await versionedGraphService.resolveVersion(graphType, {
5287
5324
  strict: false
@@ -5298,10 +5335,12 @@ function createMetaBuilder(config, versionedGraphService, moduleRef) {
5298
5335
  return versionedBuilder.buildGraph(payload);
5299
5336
  }
5300
5337
  }
5301
- async prepareConfig(payload) {
5302
- const graphType = payload.graphSettings?.graphType;
5338
+ async preparePayload(payload) {
5339
+ const graphType = payload.config?.configurable?.graphSettings?.graphType;
5303
5340
  if (!graphType) {
5304
- throw new Error("GraphType is required in payload.graphSettings");
5341
+ throw new Error(
5342
+ "GraphType is required in payload.config.configurable.graphSettings"
5343
+ );
5305
5344
  }
5306
5345
  const resolution = await versionedGraphService.resolveVersion(graphType, {
5307
5346
  strict: false
@@ -5316,9 +5355,15 @@ function createMetaBuilder(config, versionedGraphService, moduleRef) {
5316
5355
  }
5317
5356
  const updatedPayload = {
5318
5357
  ...payload,
5319
- graphSettings: {
5320
- ...payload.graphSettings,
5321
- graphType: resolution.fullGraphType
5358
+ config: {
5359
+ ...payload.config,
5360
+ configurable: {
5361
+ ...payload.config.configurable,
5362
+ graphSettings: {
5363
+ ...payload.config.configurable.graphSettings,
5364
+ graphType: resolution.fullGraphType
5365
+ }
5366
+ }
5322
5367
  }
5323
5368
  };
5324
5369
  return versionedBuilder.prepareConfig(updatedPayload);
@@ -5555,7 +5600,7 @@ exports.UniversalGraphModule = class UniversalGraphModule {
5555
5600
  "ModuleRef not available - cannot build graph"
5556
5601
  );
5557
5602
  }
5558
- async prepareConfig(payload) {
5603
+ async preparePayload(payload) {
5559
5604
  throw new Error(
5560
5605
  "ModuleRef not available - cannot prepare config"
5561
5606
  );