@flutchai/flutch-sdk 0.2.21 → 0.3.0

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
@@ -15,6 +15,7 @@ var crypto = require('crypto');
15
15
  var promClient = require('prom-client');
16
16
  var messages = require('@langchain/core/messages');
17
17
  var LangGraph = require('@langchain/langgraph');
18
+ var async_hooks = require('async_hooks');
18
19
  var dispatch = require('@langchain/core/callbacks/dispatch');
19
20
  var tools = require('@langchain/core/tools');
20
21
  var zod = require('zod');
@@ -23,6 +24,7 @@ var zodToJsonSchema = require('zod-to-json-schema');
23
24
  var manager = require('@langchain/core/callbacks/manager');
24
25
  var openai = require('@langchain/openai');
25
26
  var aws = require('@langchain/aws');
27
+ var core$1 = require('cohere-ai/core');
26
28
  var anthropic = require('@langchain/anthropic');
27
29
  var cohere = require('@langchain/cohere');
28
30
  var cohereAi = require('cohere-ai');
@@ -5302,6 +5304,71 @@ exports.EventProcessor = class EventProcessor {
5302
5304
  exports.EventProcessor = __decorateClass([
5303
5305
  common.Injectable()
5304
5306
  ], exports.EventProcessor);
5307
+ var als = new async_hooks.AsyncLocalStorage();
5308
+ function withFlutchContext(ctx, fn) {
5309
+ return als.run(ctx, fn);
5310
+ }
5311
+ function getFlutchContext() {
5312
+ return als.getStore();
5313
+ }
5314
+ var HEADER_MAP = {
5315
+ messageId: "x-flutch-message-id",
5316
+ threadId: "x-flutch-thread-id",
5317
+ agentId: "x-flutch-agent-id",
5318
+ userId: "x-flutch-user-id",
5319
+ nodeName: "x-flutch-node"
5320
+ };
5321
+ var flutchFetch = (input, init) => {
5322
+ const ctx = als.getStore();
5323
+ if (!ctx) {
5324
+ return fetch(input, init);
5325
+ }
5326
+ const headers = new Headers(init?.headers);
5327
+ for (const key of Object.keys(HEADER_MAP)) {
5328
+ const value = ctx[key];
5329
+ if (value) {
5330
+ headers.set(HEADER_MAP[key], String(value));
5331
+ }
5332
+ }
5333
+ return fetch(input, { ...init, headers });
5334
+ };
5335
+ function flutchHeaders() {
5336
+ const ctx = als.getStore();
5337
+ if (!ctx) return {};
5338
+ const out = {};
5339
+ for (const key of Object.keys(HEADER_MAP)) {
5340
+ const value = ctx[key];
5341
+ if (value) {
5342
+ out[HEADER_MAP[key]] = String(value);
5343
+ }
5344
+ }
5345
+ return out;
5346
+ }
5347
+ function flutchMistralHook(req) {
5348
+ const extras = flutchHeaders();
5349
+ if (Object.keys(extras).length === 0) {
5350
+ return req;
5351
+ }
5352
+ const headers = new Headers(req.headers);
5353
+ for (const [k, v] of Object.entries(extras)) {
5354
+ headers.set(k, v);
5355
+ }
5356
+ return new Request(req, { headers });
5357
+ }
5358
+ function wrapCohereFetcher(inner) {
5359
+ return ((args) => {
5360
+ const extras = flutchHeaders();
5361
+ if (Object.keys(extras).length === 0) {
5362
+ return inner(args);
5363
+ }
5364
+ return inner({
5365
+ ...args,
5366
+ headers: { ...args.headers ?? {}, ...extras }
5367
+ });
5368
+ });
5369
+ }
5370
+
5371
+ // src/engines/langgraph/langgraph-engine.ts
5305
5372
  process.setMaxListeners(0);
5306
5373
  exports.LangGraphEngine = class LangGraphEngine {
5307
5374
  constructor(eventProcessor, configService) {
@@ -5353,29 +5420,42 @@ exports.LangGraphEngine = class LangGraphEngine {
5353
5420
  * Method to invoke LangGraph
5354
5421
  */
5355
5422
  async invokeGraph(graph, preparedPayload, signal) {
5356
- this.logger.debug("invokeGraph preparedPayload", preparedPayload);
5357
- if (signal) {
5358
- preparedPayload.signal = signal;
5359
- this.logger.debug("[ENGINE] Signal assigned to preparedPayload.signal");
5360
- }
5361
- const input = await this.deserializeInput(preparedPayload.input || {});
5362
- try {
5363
- const result = await graph.invoke(input, {
5364
- ...preparedPayload.config,
5365
- signal: preparedPayload.signal
5366
- });
5367
- return this.processGraphResult(result);
5368
- } finally {
5369
- const threadId = this.extractThreadId(preparedPayload);
5370
- if (threadId) {
5371
- clearAttachmentDataStore(threadId);
5372
- this.logger.debug(
5373
- `[ENGINE] Cleared attachment data store for thread: ${threadId}`
5374
- );
5423
+ return withFlutchContext(
5424
+ this.extractFlutchContext(preparedPayload),
5425
+ async () => {
5426
+ this.logger.debug("invokeGraph preparedPayload", preparedPayload);
5427
+ if (signal) {
5428
+ preparedPayload.signal = signal;
5429
+ this.logger.debug(
5430
+ "[ENGINE] Signal assigned to preparedPayload.signal"
5431
+ );
5432
+ }
5433
+ const input = await this.deserializeInput(preparedPayload.input || {});
5434
+ try {
5435
+ const result = await graph.invoke(input, {
5436
+ ...preparedPayload.config,
5437
+ signal: preparedPayload.signal
5438
+ });
5439
+ return this.processGraphResult(result);
5440
+ } finally {
5441
+ const threadId = this.extractThreadId(preparedPayload);
5442
+ if (threadId) {
5443
+ clearAttachmentDataStore(threadId);
5444
+ this.logger.debug(
5445
+ `[ENGINE] Cleared attachment data store for thread: ${threadId}`
5446
+ );
5447
+ }
5448
+ }
5375
5449
  }
5376
- }
5450
+ );
5377
5451
  }
5378
5452
  async streamGraph(graph, preparedPayload, onPartial, signal) {
5453
+ return withFlutchContext(
5454
+ this.extractFlutchContext(preparedPayload),
5455
+ () => this.streamGraphInner(graph, preparedPayload, onPartial, signal)
5456
+ );
5457
+ }
5458
+ async streamGraphInner(graph, preparedPayload, onPartial, signal) {
5379
5459
  const acc = this.eventProcessor.createAccumulator();
5380
5460
  let streamError = null;
5381
5461
  this.logger.debug({
@@ -5605,6 +5685,22 @@ exports.LangGraphEngine = class LangGraphEngine {
5605
5685
  extractThreadId(preparedPayload) {
5606
5686
  return preparedPayload.configurable?.thread_id || preparedPayload.configurable?.context?.threadId || preparedPayload.config?.configurable?.thread_id || preparedPayload.config?.configurable?.context?.threadId || void 0;
5607
5687
  }
5688
+ /**
5689
+ * Extract Flutch billing/attribution context from the prepared payload.
5690
+ *
5691
+ * Read by `flutchFetch` (in node-sdk/src/models/flutch-context.ts) to
5692
+ * attach X-Flutch-* headers to every router-bound LLM call made during
5693
+ * this graph run.
5694
+ */
5695
+ extractFlutchContext(preparedPayload) {
5696
+ const ctx = preparedPayload?.config?.configurable?.context || preparedPayload?.configurable?.context || {};
5697
+ return {
5698
+ messageId: ctx.messageId,
5699
+ threadId: ctx.threadId || preparedPayload?.config?.configurable?.thread_id,
5700
+ agentId: ctx.agentId,
5701
+ userId: ctx.userId
5702
+ };
5703
+ }
5608
5704
  /**
5609
5705
  * Process graph execution result
5610
5706
  */
@@ -6760,7 +6856,10 @@ var ModelInitializer = class _ModelInitializer {
6760
6856
  );
6761
6857
  const routerURL = resolveRouterURL(baseURL);
6762
6858
  if (routerURL) {
6763
- config.configuration = { baseURL: `${routerURL}/v1` };
6859
+ config.configuration = {
6860
+ baseURL: `${routerURL}/v1`,
6861
+ fetch: flutchFetch
6862
+ };
6764
6863
  }
6765
6864
  return new openai.ChatOpenAI(config);
6766
6865
  },
@@ -6770,15 +6869,19 @@ var ModelInitializer = class _ModelInitializer {
6770
6869
  defaultMaxTokens,
6771
6870
  apiToken,
6772
6871
  baseURL
6773
- }) => new anthropic.ChatAnthropic({
6774
- modelName,
6775
- temperature: defaultTemperature,
6776
- maxTokens: defaultMaxTokens,
6777
- anthropicApiKey: apiToken || this.resolveApiKey("anthropic" /* ANTHROPIC */),
6778
- ...resolveRouterURL(baseURL) && {
6779
- anthropicApiUrl: resolveRouterURL(baseURL)
6780
- }
6781
- }),
6872
+ }) => {
6873
+ const routerURL = resolveRouterURL(baseURL);
6874
+ return new anthropic.ChatAnthropic({
6875
+ modelName,
6876
+ temperature: defaultTemperature,
6877
+ maxTokens: defaultMaxTokens,
6878
+ anthropicApiKey: apiToken || this.resolveApiKey("anthropic" /* ANTHROPIC */),
6879
+ ...routerURL && {
6880
+ anthropicApiUrl: routerURL,
6881
+ clientOptions: { fetch: flutchFetch }
6882
+ }
6883
+ });
6884
+ },
6782
6885
  ["cohere" /* COHERE */]: ({
6783
6886
  modelName,
6784
6887
  defaultTemperature,
@@ -6791,7 +6894,13 @@ var ModelInitializer = class _ModelInitializer {
6791
6894
  return routerURL ? new cohere.ChatCohere({
6792
6895
  model: modelName,
6793
6896
  temperature: defaultTemperature,
6794
- client: new cohereAi.CohereClient({ token, baseUrl: routerURL })
6897
+ client: new cohereAi.CohereClient({
6898
+ token,
6899
+ baseUrl: routerURL,
6900
+ // Inject X-Flutch-* headers from the ALS context on every
6901
+ // outbound request via the wrapped default fetcher.
6902
+ fetcher: wrapCohereFetcher(core$1.fetcher)
6903
+ })
6795
6904
  }) : new cohere.ChatCohere({
6796
6905
  model: modelName,
6797
6906
  temperature: defaultTemperature,
@@ -6811,7 +6920,13 @@ var ModelInitializer = class _ModelInitializer {
6811
6920
  temperature: defaultTemperature,
6812
6921
  maxTokens: defaultMaxTokens,
6813
6922
  apiKey: apiToken || this.resolveApiKey("mistral" /* MISTRAL */),
6814
- ...routerURL && { serverURL: `${routerURL}/v1` }
6923
+ ...routerURL && {
6924
+ serverURL: `${routerURL}/v1`,
6925
+ // Mistral SDK doesn't accept a custom fetch directly — its
6926
+ // beforeRequestHooks let us mutate the outgoing Request to add
6927
+ // X-Flutch-* headers from the ALS context.
6928
+ beforeRequestHooks: [flutchMistralHook]
6929
+ }
6815
6930
  });
6816
6931
  },
6817
6932
  ["voyageai" /* VOYAGEAI */]: () => {
@@ -6866,7 +6981,7 @@ var ModelInitializer = class _ModelInitializer {
6866
6981
  model: modelName,
6867
6982
  apiKey: apiToken || this.resolveApiKey("openai" /* OPENAI */),
6868
6983
  ...routerURL && {
6869
- configuration: { baseURL: `${routerURL}/v1` }
6984
+ configuration: { baseURL: `${routerURL}/v1`, fetch: flutchFetch }
6870
6985
  }
6871
6986
  });
6872
6987
  },
@@ -7860,11 +7975,15 @@ exports.encryptTokens = encryptTokens;
7860
7975
  exports.executeToolWithAttachments = executeToolWithAttachments;
7861
7976
  exports.findCallbackMethod = findCallbackMethod;
7862
7977
  exports.findEndpointMethod = findEndpointMethod;
7978
+ exports.flutchFetch = flutchFetch;
7979
+ exports.flutchHeaders = flutchHeaders;
7980
+ exports.flutchMistralHook = flutchMistralHook;
7863
7981
  exports.generateAttachmentSummary = generateAttachmentSummary;
7864
7982
  exports.generateModelCacheKey = generateModelCacheKey;
7865
7983
  exports.getAttachmentData = getAttachmentData;
7866
7984
  exports.getCallbackMetadata = getCallbackMetadata;
7867
7985
  exports.getEndpointMetadata = getEndpointMetadata;
7986
+ exports.getFlutchContext = getFlutchContext;
7868
7987
  exports.getOAuthProvider = getOAuthProvider;
7869
7988
  exports.getOAuthProviderNames = getOAuthProviderNames;
7870
7989
  exports.getUIEndpointClassMetadata = getUIEndpointClassMetadata;
@@ -7882,5 +8001,7 @@ exports.resolveRouterURL = resolveRouterURL;
7882
8001
  exports.sanitizeTraceData = sanitizeTraceData;
7883
8002
  exports.storeAttachmentData = storeAttachmentData;
7884
8003
  exports.traceApiCall = traceApiCall;
8004
+ exports.withFlutchContext = withFlutchContext;
8005
+ exports.wrapCohereFetcher = wrapCohereFetcher;
7885
8006
  //# sourceMappingURL=index.cjs.map
7886
8007
  //# sourceMappingURL=index.cjs.map