@softprobe/langchain 0.1.6 → 0.1.8

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.
@@ -7,8 +7,14 @@ import type { LLMResult } from "@langchain/core/outputs";
7
7
  import type { ChainValues } from "@langchain/core/utils/types";
8
8
  import { SoftprobeClient, type JsonValue } from "@softprobe/tracing";
9
9
  export type CallbackHandlerParams = {
10
- softprobeClient: SoftprobeClient;
10
+ /** Defaults to {@link SoftprobeClient.fromEnv}. */
11
+ softprobeClient?: SoftprobeClient;
12
+ /**
13
+ * Fallback only when the run has no thread/session/chat id in LangChain
14
+ * metadata / `configurable`. Prefer your app's existing ids at invoke time.
15
+ */
11
16
  sessionId?: string;
17
+ /** Fallback only when the run has no user id in metadata / `configurable`. */
12
18
  userId?: string;
13
19
  tags?: string[];
14
20
  metadata?: Record<string, JsonValue>;
@@ -31,7 +37,9 @@ export declare class CallbackHandler extends BaseCallbackHandler {
31
37
  private readonly completionStart;
32
38
  private readonly toolMeta;
33
39
  lastTraceId: string | null;
34
- constructor(params: CallbackHandlerParams);
40
+ constructor(params?: CallbackHandlerParams);
41
+ /** Flush pending OTLP spans (alias of the underlying client). */
42
+ flush(): Promise<void>;
35
43
  private parent;
36
44
  private start;
37
45
  private end;
@@ -1,5 +1,5 @@
1
1
  import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
2
- import { recordToolCalls, recordToolDefinitions, toolResultEventPayload, toolSpanAttributes, normalizeToolCalls, } from "@softprobe/tracing";
2
+ import { SoftprobeClient, resolveRunIdentity, recordToolCalls, recordToolDefinitions, toolResultEventPayload, toolSpanAttributes, normalizeToolCalls, } from "@softprobe/tracing";
3
3
  function asJsonValue(value) {
4
4
  return value;
5
5
  }
@@ -42,9 +42,9 @@ export class CallbackHandler extends BaseCallbackHandler {
42
42
  completionStart = new Map();
43
43
  toolMeta = new Map();
44
44
  lastTraceId = null;
45
- constructor(params) {
45
+ constructor(params = {}) {
46
46
  super();
47
- this.client = params.softprobeClient;
47
+ this.client = params.softprobeClient ?? SoftprobeClient.fromEnv();
48
48
  this.sessionId = params.sessionId;
49
49
  this.userId = params.userId;
50
50
  this.tags = params.tags ?? [];
@@ -52,6 +52,10 @@ export class CallbackHandler extends BaseCallbackHandler {
52
52
  this.version = params.version;
53
53
  this.parentSpanContext = params.parentSpanContext;
54
54
  }
55
+ /** Flush pending OTLP spans (alias of the underlying client). */
56
+ async flush() {
57
+ await this.client.flush();
58
+ }
55
59
  parent(parentRunId) {
56
60
  if (!parentRunId)
57
61
  return undefined;
@@ -64,10 +68,15 @@ export class CallbackHandler extends BaseCallbackHandler {
64
68
  ...(this.metadata ?? {}),
65
69
  ...(options.metadata ?? {}),
66
70
  };
71
+ const identity = resolveRunIdentity({
72
+ metadata: options.metadata,
73
+ fallbackSessionId: this.sessionId,
74
+ fallbackUserId: this.userId,
75
+ });
67
76
  const common = {
68
77
  name: options.name,
69
- sessionId: this.sessionId,
70
- userId: this.userId,
78
+ sessionId: identity.sessionId,
79
+ userId: identity.userId,
71
80
  tags: mergedTags.length ? mergedTags : undefined,
72
81
  metadata: Object.keys(mergedMeta).length ? mergedMeta : undefined,
73
82
  version: this.version,
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export { CallbackHandler, type CallbackHandlerParams, } from "./CallbackHandler.js";
2
+ export { instrument, uninstrument, autoInstrumentFromEnv, isInstrumented, getHandler, SOFTPROBE_LANGCHAIN_CONTEXT_VAR, } from "./instrument.js";
package/dist/index.js CHANGED
@@ -1 +1,5 @@
1
1
  export { CallbackHandler, } from "./CallbackHandler.js";
2
+ export { instrument, uninstrument, autoInstrumentFromEnv, isInstrumented, getHandler, SOFTPROBE_LANGCHAIN_CONTEXT_VAR, } from "./instrument.js";
3
+ import { autoInstrumentFromEnv } from "./instrument.js";
4
+ /** Best-tier UX: credentials present → auto-instrument (unless SOFTPROBE_LANGCHAIN=0). */
5
+ autoInstrumentFromEnv();
@@ -0,0 +1,8 @@
1
+ import { type SoftprobeEnvSource } from "@softprobe/tracing";
2
+ import { CallbackHandler, type CallbackHandlerParams } from "./CallbackHandler.js";
3
+ export declare const SOFTPROBE_LANGCHAIN_CONTEXT_VAR = "softprobe_langchain_handler";
4
+ export declare function isInstrumented(): boolean;
5
+ export declare function getHandler(): CallbackHandler | null;
6
+ export declare function instrument(params?: CallbackHandlerParams): CallbackHandler;
7
+ export declare function uninstrument(): void;
8
+ export declare function autoInstrumentFromEnv(params?: CallbackHandlerParams, env?: SoftprobeEnvSource): CallbackHandler | null;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Zero-setup LangChain instrumentation (env auto + `instrument()`).
3
+ *
4
+ * When SOFTPROBE_PUBLIC_KEY and SOFTPROBE_BASE_URL are set, Softprobe
5
+ * registers into LangChain configure hooks so every run is traced without
6
+ * editing `callbacks`.
7
+ *
8
+ * Opt out: SOFTPROBE_LANGCHAIN=0
9
+ */
10
+ import { registerConfigureHook, setContextVariable, } from "@langchain/core/context";
11
+ import { resolveSoftprobeConfigFromEnv, } from "@softprobe/tracing";
12
+ import { CallbackHandler, } from "./CallbackHandler.js";
13
+ export const SOFTPROBE_LANGCHAIN_CONTEXT_VAR = "softprobe_langchain_handler";
14
+ let hookRegistered = false;
15
+ let activeHandler = null;
16
+ function envFlagDisabled(env = process.env, name = "SOFTPROBE_LANGCHAIN") {
17
+ const raw = env[name];
18
+ if (raw == null)
19
+ return false;
20
+ return ["0", "false", "off", "no"].includes(raw.trim().toLowerCase());
21
+ }
22
+ export function isInstrumented() {
23
+ return activeHandler != null;
24
+ }
25
+ export function getHandler() {
26
+ return activeHandler;
27
+ }
28
+ export function instrument(params = {}) {
29
+ if (!hookRegistered) {
30
+ registerConfigureHook({
31
+ contextVar: SOFTPROBE_LANGCHAIN_CONTEXT_VAR,
32
+ inheritable: true,
33
+ });
34
+ hookRegistered = true;
35
+ }
36
+ if (activeHandler == null || Object.keys(params).length > 0) {
37
+ activeHandler = new CallbackHandler(params);
38
+ }
39
+ setContextVariable(SOFTPROBE_LANGCHAIN_CONTEXT_VAR, activeHandler);
40
+ return activeHandler;
41
+ }
42
+ export function uninstrument() {
43
+ setContextVariable(SOFTPROBE_LANGCHAIN_CONTEXT_VAR, undefined);
44
+ activeHandler = null;
45
+ }
46
+ export function autoInstrumentFromEnv(params = {}, env = process.env) {
47
+ if (envFlagDisabled(env))
48
+ return null;
49
+ if (!resolveSoftprobeConfigFromEnv(env))
50
+ return null;
51
+ return instrument(params);
52
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softprobe/langchain",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Softprobe LangChain callback handler",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,7 +25,7 @@
25
25
  "lint": "tsc -p tsconfig.json --noEmit"
26
26
  },
27
27
  "dependencies": {
28
- "@softprobe/tracing": "0.1.6"
28
+ "@softprobe/tracing": "0.1.8"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@langchain/core": ">=0.3.0",