@flutchai/flutch-sdk 0.2.19 → 0.2.21

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
@@ -4817,6 +4817,36 @@ exports.EventProcessor = class EventProcessor {
4817
4817
  }
4818
4818
  return [];
4819
4819
  }
4820
+ /**
4821
+ * Convert LangChain unified `tool_call_chunks` (Bedrock / OpenAI streaming
4822
+ * format) into Anthropic-style blocks so the rest of the pipeline can stay
4823
+ * uniform. The first chunk for a tool carries `name` (and usually `id`);
4824
+ * subsequent chunks carry partial `args` strings that need to accumulate.
4825
+ *
4826
+ * NOTE: assumes tool calls arrive sequentially. Parallel tool calls with
4827
+ * interleaved `args` chunks across different `index`es will misroute args
4828
+ * to the most recently opened tool_use block.
4829
+ */
4830
+ toolCallChunksToBlocks(toolCallChunks) {
4831
+ const blocks = [];
4832
+ for (const tcc of toolCallChunks) {
4833
+ if (tcc.name) {
4834
+ blocks.push({
4835
+ type: "tool_use",
4836
+ id: tcc.id,
4837
+ name: tcc.name,
4838
+ input: ""
4839
+ });
4840
+ }
4841
+ if (typeof tcc.args === "string" && tcc.args.length > 0) {
4842
+ blocks.push({
4843
+ type: "input_json_delta",
4844
+ input: tcc.args
4845
+ });
4846
+ }
4847
+ }
4848
+ return blocks;
4849
+ }
4820
4850
  /**
4821
4851
  * Extract attachments from various input formats
4822
4852
  * Handles both array format (IAttachment[]) and object format (Record<string, IGraphAttachment>)
@@ -4980,10 +5010,19 @@ exports.EventProcessor = class EventProcessor {
4980
5010
  }
4981
5011
  return;
4982
5012
  }
4983
- if (event.event === "on_chat_model_stream" && event.data?.chunk?.content) {
5013
+ if (event.event === "on_chat_model_stream" && event.data?.chunk) {
4984
5014
  const channel = event.metadata?.stream_channel ?? "text" /* TEXT */;
4985
- const blocks = this.normalizeContentBlocks(event.data.chunk.content);
4986
- this.processContentStream(acc, channel, blocks, onPartial);
5015
+ const chunk = event.data.chunk;
5016
+ const blocks = [];
5017
+ if (chunk.content) {
5018
+ blocks.push(...this.normalizeContentBlocks(chunk.content));
5019
+ }
5020
+ if (Array.isArray(chunk.tool_call_chunks) && chunk.tool_call_chunks.length > 0) {
5021
+ blocks.push(...this.toolCallChunksToBlocks(chunk.tool_call_chunks));
5022
+ }
5023
+ if (blocks.length > 0) {
5024
+ this.processContentStream(acc, channel, blocks, onPartial);
5025
+ }
4987
5026
  return;
4988
5027
  }
4989
5028
  if (event.event === "on_tool_start") {
@@ -4996,6 +5035,44 @@ exports.EventProcessor = class EventProcessor {
4996
5035
  if (idx !== -1) {
4997
5036
  const block = state.pendingToolBlocks.splice(idx, 1)[0];
4998
5037
  state.toolBlocksByRunId.set(event.run_id, block);
5038
+ } else {
5039
+ const toolInput = event.data?.input;
5040
+ let inputString;
5041
+ try {
5042
+ inputString = typeof toolInput === "string" ? toolInput : JSON.stringify(toolInput ?? {});
5043
+ } catch {
5044
+ inputString = "";
5045
+ }
5046
+ const synthesizedBlock = {
5047
+ index: state.contentChain.length + (state.currentBlock ? 1 : 0),
5048
+ type: "tool_use",
5049
+ name: event.name,
5050
+ id: event.run_id,
5051
+ input: inputString,
5052
+ output: ""
5053
+ };
5054
+ if (state.currentBlock) {
5055
+ state.contentChain.push(state.currentBlock);
5056
+ state.currentBlock = null;
5057
+ }
5058
+ state.contentChain.push(synthesizedBlock);
5059
+ state.toolBlocksByRunId.set(event.run_id, synthesizedBlock);
5060
+ this.sendDelta(
5061
+ channel,
5062
+ { type: "step_started", step: synthesizedBlock },
5063
+ onPartial
5064
+ );
5065
+ if (inputString.length > 0) {
5066
+ this.sendDelta(
5067
+ channel,
5068
+ {
5069
+ type: "tool_input_chunk",
5070
+ stepId: synthesizedBlock.id,
5071
+ chunk: inputString
5072
+ },
5073
+ onPartial
5074
+ );
5075
+ }
4999
5076
  }
5000
5077
  }
5001
5078
  this.logger.log("\u{1F527} Tool execution started", {
@@ -5362,11 +5439,11 @@ exports.LangGraphEngine = class LangGraphEngine {
5362
5439
  * Extract trace from accumulator and send to backend webhook
5363
5440
  * Called in finally block to ensure trace is sent even on errors
5364
5441
  */
5365
- async sendTraceFromAccumulator(acc, config, error) {
5442
+ async sendTraceFromAccumulator(acc, preparedPayload, error) {
5366
5443
  try {
5367
5444
  const { trace } = this.eventProcessor.getResult(acc);
5368
- if (trace && trace.events.length > 0 && config.configurable?.context) {
5369
- const context = config.configurable.context;
5445
+ const context = preparedPayload.config?.configurable?.context || preparedPayload.configurable?.context;
5446
+ if (trace && trace.events.length > 0 && context) {
5370
5447
  this.logger.debug("[TRACE-WEBHOOK] Sending trace events batch", {
5371
5448
  messageId: context.messageId,
5372
5449
  totalEvents: trace.totalEvents,
@@ -5393,8 +5470,8 @@ exports.LangGraphEngine = class LangGraphEngine {
5393
5470
  this.logger.debug("[TRACE-WEBHOOK] Skipping webhook", {
5394
5471
  hasTrace: !!trace,
5395
5472
  traceEvents: trace?.events?.length || 0,
5396
- hasContext: !!config.configurable?.context,
5397
- contextKeys: config.configurable?.context ? Object.keys(config.configurable.context) : [],
5473
+ hasContext: !!context,
5474
+ contextKeys: context ? Object.keys(context) : [],
5398
5475
  hadError: !!error
5399
5476
  });
5400
5477
  }