@posthog/ai 8.6.0 → 8.6.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.
@@ -217,7 +217,7 @@ function sanitizeValues(obj) {
217
217
  return jsonSafe;
218
218
  }
219
219
 
220
- var version = "8.6.0";
220
+ var version = "8.6.2";
221
221
 
222
222
  const DEFAULT_MAX_DEPTH = 3;
223
223
  const MAX_STACK_LINES = 20;
@@ -308,6 +308,13 @@ const warnIfPostHogAiGateway = baseURL => {
308
308
  console.warn('[PostHog] The PostHog AI wrapper is pointed at the PostHog AI Gateway. ' + 'Both capture $ai_generation, so every call is double-counted and double-billed. ' + `Use one or the other — see ${GATEWAY_DOCS_URL}.`);
309
309
  };
310
310
 
311
+ // Mirror LangGraph's isGraphBubbleUp guard without adding LangGraph as a dependency. Every
312
+ // LangGraph control-flow exception (GraphInterrupt, NodeInterrupt, ParentCommand, GraphDrained,
313
+ // and future subclasses) exposes a prototype getter `is_bubble_up` that returns true, which the
314
+ // LangGraph runtime itself uses to distinguish control flow from real failures. The getter reads
315
+ // as undefined on ordinary Errors and works across duplicated LangGraph package copies.
316
+ const isLangGraphControlFlow = error => error.is_bubble_up === true;
317
+
311
318
  /** A run may either be a Span or a Generation */
312
319
 
313
320
  /** Storage for run metadata */
@@ -559,8 +566,20 @@ class LangChainCallbackHandler extends base.BaseCallbackHandler {
559
566
  eventProperties['$process_person_profile'] = false;
560
567
  }
561
568
  if (outputs instanceof Error) {
562
- eventProperties['$ai_error'] = stringifyError(outputs);
563
- eventProperties['$ai_is_error'] = true;
569
+ if (isLangGraphControlFlow(outputs)) {
570
+ // GraphInterrupt carries the pending interrupts (e.g. the question posed to a human).
571
+ // Surface them under the same `__interrupt__` key LangGraph hands back to the caller,
572
+ // so an interrupted span stays distinguishable from a node that returned nothing.
573
+ const interrupts = outputs.interrupts;
574
+ if (interrupts !== undefined) {
575
+ eventProperties['$ai_output_state'] = withPrivacyMode(this.client, this.privacyMode, sanitizeLangChain({
576
+ __interrupt__: interrupts
577
+ }));
578
+ }
579
+ } else {
580
+ eventProperties['$ai_error'] = stringifyError(outputs);
581
+ eventProperties['$ai_is_error'] = true;
582
+ }
564
583
  } else if (outputs !== undefined) {
565
584
  eventProperties['$ai_output_state'] = withPrivacyMode(this.client, this.privacyMode, sanitizeLangChain(outputs));
566
585
  }
@@ -785,27 +804,10 @@ class LangChainCallbackHandler extends base.BaseCallbackHandler {
785
804
  return undefined;
786
805
  }
787
806
  const gen = lastGeneration[0];
788
-
789
- // Check generationInfo for finish_reason (OpenAI format)
790
- if (gen.generationInfo?.finish_reason) {
791
- return String(gen.generationInfo.finish_reason);
792
- }
793
-
794
- // Check generationInfo for response_metadata.stop_reason (Anthropic format)
795
- if (gen.generationInfo?.response_metadata?.stop_reason) {
796
- return String(gen.generationInfo.response_metadata.stop_reason);
797
- }
798
-
799
- // Check message response_metadata for finish_reason (common LangChain format)
800
- if (gen.generationInfo?.response_metadata?.finish_reason) {
801
- return String(gen.generationInfo.response_metadata.finish_reason);
802
- }
803
-
804
- // Check for stop_reason directly in generationInfo
805
- if (gen.generationInfo?.stop_reason) {
806
- return String(gen.generationInfo.stop_reason);
807
- }
808
- return undefined;
807
+ const messageResponseMetadata = gen.message?.response_metadata;
808
+ const generationResponseMetadata = gen.generationInfo?.response_metadata;
809
+ const stopReason = messageResponseMetadata?.finish_reason || messageResponseMetadata?.stop_reason || gen.generationInfo?.finish_reason || generationResponseMetadata?.stop_reason || generationResponseMetadata?.finish_reason || gen.generationInfo?.stop_reason;
810
+ return stopReason != null ? String(stopReason) : undefined;
809
811
  }
810
812
  _parseUsageModel(usage, provider, model) {
811
813
  const conversionList = [['promptTokens', 'input'], ['completionTokens', 'output'], ['input_tokens', 'input'], ['output_tokens', 'output'], ['prompt_token_count', 'input'], ['candidates_token_count', 'output'], ['inputTokenCount', 'input'], ['outputTokenCount', 'output'], ['input_token_count', 'input'], ['generated_token_count', 'output']];
@@ -923,14 +925,11 @@ class LangChainCallbackHandler extends base.BaseCallbackHandler {
923
925
  if (llmUsage[0] === 0 && llmUsage[1] === 0 && response.generations) {
924
926
  for (const generation of response.generations) {
925
927
  for (const genChunk of generation) {
926
- // Check other paths for usage information
927
- if (genChunk.generationInfo?.usage_metadata) {
928
- llmUsage = this._parseUsageModel(genChunk.generationInfo.usage_metadata, provider, model);
929
- return llmUsage;
930
- }
931
- const messageChunk = genChunk.generationInfo ?? {};
932
- const responseMetadata = messageChunk.response_metadata ?? {};
933
- const chunkUsage = responseMetadata['usage'] ?? responseMetadata['amazon-bedrock-invocationMetrics'] ?? messageChunk.usage_metadata;
928
+ const message = genChunk.message ?? {};
929
+ const messageResponseMetadata = message.response_metadata ?? {};
930
+ const generationInfo = genChunk.generationInfo ?? {};
931
+ const generationResponseMetadata = generationInfo.response_metadata ?? {};
932
+ const chunkUsage = message.usage_metadata ?? messageResponseMetadata['usage'] ?? messageResponseMetadata['amazon-bedrock-invocationMetrics'] ?? generationInfo.usage_metadata ?? generationResponseMetadata['usage'] ?? generationResponseMetadata['amazon-bedrock-invocationMetrics'];
934
933
  if (chunkUsage) {
935
934
  llmUsage = this._parseUsageModel(chunkUsage, provider, model);
936
935
  return llmUsage;