darwin-langgraph 0.2.0-alpha.1 → 0.4.0-alpha.1

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +348 -0
  2. package/README.md +108 -3
  3. package/dist/create-darwin-node.d.ts +55 -0
  4. package/dist/create-darwin-node.d.ts.map +1 -1
  5. package/dist/create-darwin-node.js +56 -1
  6. package/dist/create-darwin-node.js.map +1 -1
  7. package/dist/darwin-accumulating-annotation.d.ts +81 -0
  8. package/dist/darwin-accumulating-annotation.d.ts.map +1 -0
  9. package/dist/darwin-accumulating-annotation.js +144 -0
  10. package/dist/darwin-accumulating-annotation.js.map +1 -0
  11. package/dist/darwin-callback-handler.d.ts +161 -2
  12. package/dist/darwin-callback-handler.d.ts.map +1 -1
  13. package/dist/darwin-callback-handler.js +417 -25
  14. package/dist/darwin-callback-handler.js.map +1 -1
  15. package/dist/errors.d.ts +16 -0
  16. package/dist/errors.d.ts.map +1 -1
  17. package/dist/errors.js +19 -0
  18. package/dist/errors.js.map +1 -1
  19. package/dist/index.d.ts +7 -3
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +11 -3
  22. package/dist/index.js.map +1 -1
  23. package/dist/to-otel-attributes.d.ts +49 -0
  24. package/dist/to-otel-attributes.d.ts.map +1 -1
  25. package/dist/to-otel-attributes.js +38 -2
  26. package/dist/to-otel-attributes.js.map +1 -1
  27. package/dist/to-w3c-trace-context.d.ts +81 -0
  28. package/dist/to-w3c-trace-context.d.ts.map +1 -0
  29. package/dist/to-w3c-trace-context.js +134 -0
  30. package/dist/to-w3c-trace-context.js.map +1 -0
  31. package/dist/token-budget.d.ts +141 -0
  32. package/dist/token-budget.d.ts.map +1 -0
  33. package/dist/token-budget.js +225 -0
  34. package/dist/token-budget.js.map +1 -0
  35. package/dist/with-darwin-evolution.d.ts +40 -0
  36. package/dist/with-darwin-evolution.d.ts.map +1 -1
  37. package/dist/with-darwin-evolution.js +55 -1
  38. package/dist/with-darwin-evolution.js.map +1 -1
  39. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -41,12 +41,20 @@ export { createDarwinNode, } from "./create-darwin-node.js";
41
41
  export { darwinAnnotation, getDarwinChannelSpec, lastWriteWinsTrajectoryReducer, } from "./darwin-annotation.js";
42
42
  export { withDarwinEvolution, } from "./with-darwin-evolution.js";
43
43
  // V0.2 — LangChain-native callback handler (preferred over `withDarwinEvolution`)
44
- export { DarwinCallbackHandler } from "./darwin-callback-handler.js";
44
+ // V0.4 extended with onToolEvent + maxTrajectoryBytes + MAX_KNOWN_TRACE_VERSION
45
+ export { DarwinCallbackHandler, MAX_KNOWN_TRACE_VERSION, } from "./darwin-callback-handler.js";
45
46
  // V0.2 — OTEL GenAI Semantic Conventions mapping
47
+ // V0.4 — extended with langGraphNode / langGraphStep / userId / requestId
46
48
  export { toOtelAttributes, toolCallToOtelAttributes, } from "./to-otel-attributes.js";
47
49
  // V0.2 — MessagesAnnotation interop for graphs mixing createReactAgent + createDarwinNode
48
50
  export { darwinMessagesAnnotation, getMessagesChannelSpec, } from "./darwin-messages-annotation.js";
49
- export { DarwinNodeError, DarwinEvolutionHookError } from "./errors.js";
51
+ // V0.4 accumulating annotation for graphs that fan-out multiple Darwin nodes
52
+ export { darwinAccumulatingAnnotation, getDarwinAccumulatingChannelSpec, darwinTrajectoryAccumulatorReducer, } from "./darwin-accumulating-annotation.js";
53
+ // V0.4 — token-budget callbacks (production guard against runaway agents)
54
+ export { TokenBudgetCallbackHandler, createTokenBudgetCallbacks, } from "./token-budget.js";
55
+ // V0.4 — W3C Trace Context mapper for cross-process span correlation
56
+ export { toW3CTraceContext, } from "./to-w3c-trace-context.js";
57
+ export { DarwinNodeError, DarwinEvolutionHookError, DarwinTokenBudgetExceededError, } from "./errors.js";
50
58
  /** Adapter version — sync with `package.json` on every release. */
51
- export const VERSION = "0.2.0-alpha.1";
59
+ export const VERSION = "0.4.0-alpha.1";
52
60
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EACL,gBAAgB,GAIjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,8BAA8B,GAC/B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,mBAAmB,GAIpB,MAAM,4BAA4B,CAAC;AAEpC,kFAAkF;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,iDAAiD;AACjD,OAAO,EACL,gBAAgB,EAChB,wBAAwB,GAIzB,MAAM,yBAAyB,CAAC;AAEjC,0FAA0F;AAC1F,OAAO,EACL,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAaxE,mEAAmE;AACnE,MAAM,CAAC,MAAM,OAAO,GAAG,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EACL,gBAAgB,GAIjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,8BAA8B,GAC/B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,mBAAmB,GAIpB,MAAM,4BAA4B,CAAC;AAEpC,kFAAkF;AAClF,kFAAkF;AAClF,OAAO,EACL,qBAAqB,EACrB,uBAAuB,GAGxB,MAAM,8BAA8B,CAAC;AAEtC,iDAAiD;AACjD,0EAA0E;AAC1E,OAAO,EACL,gBAAgB,EAChB,wBAAwB,GAIzB,MAAM,yBAAyB,CAAC;AAEjC,0FAA0F;AAC1F,OAAO,EACL,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,iCAAiC,CAAC;AAEzC,+EAA+E;AAC/E,OAAO,EACL,4BAA4B,EAC5B,gCAAgC,EAChC,kCAAkC,GACnC,MAAM,qCAAqC,CAAC;AAE7C,0EAA0E;AAC1E,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,GAI3B,MAAM,mBAAmB,CAAC;AAE3B,qEAAqE;AACrE,OAAO,EACL,iBAAiB,GAGlB,MAAM,2BAA2B,CAAC;AAKnC,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,8BAA8B,GAC/B,MAAM,aAAa,CAAC;AAarB,mEAAmE;AACnE,MAAM,CAAC,MAAM,OAAO,GAAG,eAAe,CAAC"}
@@ -51,6 +51,55 @@ export interface ToOtelAttributesOptions {
51
51
  * Override for organisation-wide naming conventions (e.g. `"company.darwin"`).
52
52
  */
53
53
  customNamespace?: string;
54
+ /**
55
+ * V0.4 — LangGraph node name. Emits `gen_ai.langgraph.node` per the
56
+ * Coralogix / Last9 / Honeycomb convention for LangGraph instrumentation.
57
+ *
58
+ * Pass `event.nodeName` from {@link DarwinTrajectoryEvent} to populate.
59
+ *
60
+ * NEW V0.4 (S1235).
61
+ */
62
+ langGraphNode?: string;
63
+ /**
64
+ * V0.4 — LangGraph step counter for this node execution. Emits
65
+ * `gen_ai.langgraph.step`. Optional — LangGraph does not always surface
66
+ * the step counter through callbacks; consumers who track it can
67
+ * forward it here.
68
+ *
69
+ * NEW V0.4 (S1235).
70
+ */
71
+ langGraphStep?: number;
72
+ /**
73
+ * V0.4 — End-user id (the authenticated user the request was made on
74
+ * behalf of). Emits the OTel cross-cutting `enduser.id` attribute
75
+ * (the canonical OTel general-semconv attribute for end-user identity)
76
+ * AND the historical alias `gen_ai.request.user` that older Coralogix /
77
+ * Last9 dashboards key off.
78
+ *
79
+ * R1 Research Finding 1 (S1235): the GenAI semconv registry does NOT
80
+ * define `gen_ai.request.user` or `gen_ai.user.id` — `enduser.id` from
81
+ * the cross-cutting attributes is the spec-correct key. We emit both
82
+ * so users on either dashboard convention keep working.
83
+ *
84
+ * NEW V0.4 (S1235).
85
+ */
86
+ userId?: string;
87
+ /**
88
+ * V0.4 — Conversation / thread id (typically the LangGraph
89
+ * `thread_id` from `config.configurable`). Emits the OTel
90
+ * `gen_ai.conversation.id` attribute (canonical spec key for grouping
91
+ * spans into one logical conversation in Langfuse / Honeycomb).
92
+ *
93
+ * NEW V0.4 (S1235).
94
+ */
95
+ conversationId?: string;
96
+ /**
97
+ * V0.4 — Custom request id (correlates with upstream HTTP request
98
+ * tracing). Emits `gen_ai.request.id`. Optional.
99
+ *
100
+ * NEW V0.4 (S1235).
101
+ */
102
+ requestId?: string;
54
103
  }
55
104
  /** Flat attribute bag matching OTEL's primitive-only attribute types. */
56
105
  export type OtelAttributes = Record<string, string | number | boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"to-otel-attributes.d.ts","sourceRoot":"","sources":["../src/to-otel-attributes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,oDAAoD;AACpD,MAAM,WAAW,uBAAuB;IACtC,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,yEAAyE;AACzE,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,cAAc,EAC1B,IAAI,GAAE,uBAA4B,GACjC,cAAc,CAmEhB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gEAAgE;IAChE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EACzC,IAAI,GAAE,mBAAwB,GAC7B,cAAc,CAoDhB"}
1
+ {"version":3,"file":"to-otel-attributes.d.ts","sourceRoot":"","sources":["../src/to-otel-attributes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,oDAAoD;AACpD,MAAM,WAAW,uBAAuB;IACtC,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,yEAAyE;AACzE,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,cAAc,EAC1B,IAAI,GAAE,uBAA4B,GACjC,cAAc,CA8GhB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gEAAgE;IAChE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EACzC,IAAI,GAAE,mBAAwB,GAC7B,cAAc,CAoDhB"}
@@ -68,8 +68,17 @@
68
68
  * ```
69
69
  */
70
70
  export function toOtelAttributes(trajectory, opts = {}) {
71
- if (!trajectory || typeof trajectory !== "object" || trajectory.version !== 1) {
72
- throw new TypeError(`toOtelAttributes: trajectory must be an ExecutionTrace with version=1, got ${trajectory === null ? "null" : typeof trajectory}`);
71
+ // R2 MUST-FIX (S1235): forward-compat accept `version >= 1` to
72
+ // match the R1 P0-2 widening in `isExecutionTrace` and the
73
+ // accumulator reducer. A v=2 trajectory that passed both upstream
74
+ // gates would otherwise crash here. Same structural guard as
75
+ // `isExecutionTrace`.
76
+ if (!trajectory ||
77
+ typeof trajectory !== "object" ||
78
+ typeof trajectory.version !== "number" ||
79
+ !Number.isFinite(trajectory.version) ||
80
+ trajectory.version < 1) {
81
+ throw new TypeError(`toOtelAttributes: trajectory must be an ExecutionTrace with version>=1, got ${trajectory === null ? "null" : typeof trajectory}`);
73
82
  }
74
83
  const ns = opts.customNamespace ?? "darwin";
75
84
  const attrs = {
@@ -80,6 +89,33 @@ export function toOtelAttributes(trajectory, opts = {}) {
80
89
  attrs["gen_ai.agent.name"] = opts.agentName;
81
90
  if (opts.agentId)
82
91
  attrs["gen_ai.agent.id"] = opts.agentId;
92
+ // V0.4 (S1235): LangGraph-specific attributes per Coralogix / Last9 /
93
+ // Honeycomb 2026 convention for LangGraph instrumentation. Emitted
94
+ // alongside the canonical gen_ai attrs so dashboards that filter by
95
+ // `gen_ai.langgraph.node` (one bar per node) work out-of-box.
96
+ if (typeof opts.langGraphNode === "string" && opts.langGraphNode.length > 0) {
97
+ attrs["gen_ai.langgraph.node"] = opts.langGraphNode;
98
+ }
99
+ if (typeof opts.langGraphStep === "number" &&
100
+ Number.isFinite(opts.langGraphStep) &&
101
+ opts.langGraphStep >= 0) {
102
+ attrs["gen_ai.langgraph.step"] = opts.langGraphStep;
103
+ }
104
+ if (typeof opts.userId === "string" && opts.userId.length > 0) {
105
+ // R1 Research 1 fix (S1235): emit the OTel-spec-canonical
106
+ // `enduser.id` AND the historical alias `gen_ai.request.user` that
107
+ // older Coralogix / Last9 dashboards key off, so both consumer
108
+ // conventions keep working.
109
+ attrs["enduser.id"] = opts.userId;
110
+ attrs["gen_ai.request.user"] = opts.userId;
111
+ }
112
+ if (typeof opts.conversationId === "string" &&
113
+ opts.conversationId.length > 0) {
114
+ attrs["gen_ai.conversation.id"] = opts.conversationId;
115
+ }
116
+ if (typeof opts.requestId === "string" && opts.requestId.length > 0) {
117
+ attrs["gen_ai.request.id"] = opts.requestId;
118
+ }
83
119
  // Token usage — only emit when provider reported FINITE numbers. NaN
84
120
  // and Infinity pass `typeof === "number"` but OTEL exporters drop
85
121
  // spans with non-finite numeric attrs silently (R1 V0.2 Critic
@@ -1 +1 @@
1
- {"version":3,"file":"to-otel-attributes.js","sourceRoot":"","sources":["../src/to-otel-attributes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"to-otel-attributes.js","sourceRoot":"","sources":["../src/to-otel-attributes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Surface 11 (V0.4) — `toW3CTraceContext(event, opts?)`.
3
+ *
4
+ * Pure mapper from a {@link DarwinTrajectoryEvent} to the
5
+ * [W3C Trace Context](https://www.w3.org/TR/trace-context/) `traceparent`
6
+ * header format so consumers can propagate Darwin trajectories into
7
+ * external systems (Langfuse, Honeycomb, Datadog APM, Tempo) without
8
+ * pulling in `@opentelemetry/api` as a dependency.
9
+ *
10
+ * Format reference (spec §3.2.2):
11
+ *
12
+ * traceparent = version "-" trace-id "-" parent-id "-" trace-flags
13
+ *
14
+ * - `version` = `"00"` (we emit only the current spec version).
15
+ * - `trace-id` = 32 hex chars. We map LangChain's UUID `parentRunId` (if
16
+ * present) by stripping dashes — UUID is 32 hex chars + 4 dashes — so
17
+ * the strip yields exactly 32 chars. If `parentRunId` is undefined we
18
+ * fall back to `runId` (top-level invokes form their own trace).
19
+ * - `parent-id` = 16 hex chars. We map LangChain's UUID `runId` by
20
+ * stripping dashes and TAKING THE FIRST 16 chars (parent-id is shorter
21
+ * than trace-id by spec design — first 16 chars of a UUID are random
22
+ * enough that collision probability per-trace is negligible).
23
+ * - `trace-flags` = `"01"` (sampled). We always emit sampled — consumers
24
+ * that want head-based sampling should drop the entire event upstream
25
+ * rather than fiddle with the flag.
26
+ *
27
+ * The W3C spec forbids `trace-id == "00000000000000000000000000000000"`
28
+ * and `parent-id == "0000000000000000"`. If either UUID strips to those
29
+ * all-zero strings we return `undefined` rather than emit an invalid
30
+ * header that downstream parsers reject.
31
+ *
32
+ * **Pure, no I/O, no allocation surprises.** The function builds a single
33
+ * string. Safe to call inside `onTrajectory` hot paths.
34
+ *
35
+ * NEW V0.4 (S1235).
36
+ */
37
+ import type { DarwinTrajectoryEvent } from "./with-darwin-evolution.js";
38
+ /** Options accepted by {@link toW3CTraceContext}. */
39
+ export interface ToW3CTraceContextOptions {
40
+ /**
41
+ * Override the trace-flags byte. Default `"01"` (sampled). Set `"00"`
42
+ * for not-sampled — consumers can use this to mark trajectories that
43
+ * would otherwise be sampled out before they reach the W3C-aware
44
+ * exporter.
45
+ */
46
+ traceFlags?: "00" | "01";
47
+ }
48
+ /** Return shape: a single W3C-compliant `traceparent` header value. */
49
+ export interface W3CTraceContext {
50
+ /** Full `traceparent` header value (spec §3.2). */
51
+ traceparent: string;
52
+ /** 32-hex trace ID — convenience accessor. */
53
+ traceId: string;
54
+ /** 16-hex span ID (the W3C `parent-id` slot) — convenience accessor. */
55
+ spanId: string;
56
+ }
57
+ /**
58
+ * Convert a {@link DarwinTrajectoryEvent} into a W3C `traceparent` header
59
+ * value. Returns `undefined` when no usable runId is present or when the
60
+ * stripped UUIDs collapse to the all-zero strings the spec forbids.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * import { toW3CTraceContext, DarwinCallbackHandler } from "darwin-langgraph";
65
+ *
66
+ * const handler = new DarwinCallbackHandler({
67
+ * nodeMap: { research: "researcher" },
68
+ * onTrajectory: async (event) => {
69
+ * const ctx = toW3CTraceContext(event);
70
+ * if (!ctx) return;
71
+ * await fetch("https://langfuse.example/api/traces", {
72
+ * method: "POST",
73
+ * headers: { traceparent: ctx.traceparent },
74
+ * body: JSON.stringify({ trace: event.trajectory }),
75
+ * });
76
+ * },
77
+ * });
78
+ * ```
79
+ */
80
+ export declare function toW3CTraceContext(event: DarwinTrajectoryEvent, opts?: ToW3CTraceContextOptions): W3CTraceContext | undefined;
81
+ //# sourceMappingURL=to-w3c-trace-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to-w3c-trace-context.d.ts","sourceRoot":"","sources":["../src/to-w3c-trace-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAExE,qDAAqD;AACrD,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CAC1B;AAED,uEAAuE;AACvE,MAAM,WAAW,eAAe;IAC9B,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;CAChB;AAsBD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,qBAAqB,EAC5B,IAAI,GAAE,wBAA6B,GAClC,eAAe,GAAG,SAAS,CAwD7B"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Surface 11 (V0.4) — `toW3CTraceContext(event, opts?)`.
3
+ *
4
+ * Pure mapper from a {@link DarwinTrajectoryEvent} to the
5
+ * [W3C Trace Context](https://www.w3.org/TR/trace-context/) `traceparent`
6
+ * header format so consumers can propagate Darwin trajectories into
7
+ * external systems (Langfuse, Honeycomb, Datadog APM, Tempo) without
8
+ * pulling in `@opentelemetry/api` as a dependency.
9
+ *
10
+ * Format reference (spec §3.2.2):
11
+ *
12
+ * traceparent = version "-" trace-id "-" parent-id "-" trace-flags
13
+ *
14
+ * - `version` = `"00"` (we emit only the current spec version).
15
+ * - `trace-id` = 32 hex chars. We map LangChain's UUID `parentRunId` (if
16
+ * present) by stripping dashes — UUID is 32 hex chars + 4 dashes — so
17
+ * the strip yields exactly 32 chars. If `parentRunId` is undefined we
18
+ * fall back to `runId` (top-level invokes form their own trace).
19
+ * - `parent-id` = 16 hex chars. We map LangChain's UUID `runId` by
20
+ * stripping dashes and TAKING THE FIRST 16 chars (parent-id is shorter
21
+ * than trace-id by spec design — first 16 chars of a UUID are random
22
+ * enough that collision probability per-trace is negligible).
23
+ * - `trace-flags` = `"01"` (sampled). We always emit sampled — consumers
24
+ * that want head-based sampling should drop the entire event upstream
25
+ * rather than fiddle with the flag.
26
+ *
27
+ * The W3C spec forbids `trace-id == "00000000000000000000000000000000"`
28
+ * and `parent-id == "0000000000000000"`. If either UUID strips to those
29
+ * all-zero strings we return `undefined` rather than emit an invalid
30
+ * header that downstream parsers reject.
31
+ *
32
+ * **Pure, no I/O, no allocation surprises.** The function builds a single
33
+ * string. Safe to call inside `onTrajectory` hot paths.
34
+ *
35
+ * NEW V0.4 (S1235).
36
+ */
37
+ const ZERO_TRACE_ID = "00000000000000000000000000000000";
38
+ const ZERO_SPAN_ID = "0000000000000000";
39
+ function uuidToHex(uuid) {
40
+ // UUIDs are case-insensitive hex; lowercase to match the W3C spec.
41
+ return uuid.replace(/-/g, "").toLowerCase();
42
+ }
43
+ function isPureHex(s) {
44
+ // Cheap test — characters 0-9, a-f. ASCII range check is faster than
45
+ // a regex on hot paths.
46
+ for (let i = 0; i < s.length; i++) {
47
+ const c = s.charCodeAt(i);
48
+ const isDigit = c >= 48 && c <= 57; // 0-9
49
+ const isLowerHex = c >= 97 && c <= 102; // a-f
50
+ if (!isDigit && !isLowerHex)
51
+ return false;
52
+ }
53
+ return true;
54
+ }
55
+ /**
56
+ * Convert a {@link DarwinTrajectoryEvent} into a W3C `traceparent` header
57
+ * value. Returns `undefined` when no usable runId is present or when the
58
+ * stripped UUIDs collapse to the all-zero strings the spec forbids.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * import { toW3CTraceContext, DarwinCallbackHandler } from "darwin-langgraph";
63
+ *
64
+ * const handler = new DarwinCallbackHandler({
65
+ * nodeMap: { research: "researcher" },
66
+ * onTrajectory: async (event) => {
67
+ * const ctx = toW3CTraceContext(event);
68
+ * if (!ctx) return;
69
+ * await fetch("https://langfuse.example/api/traces", {
70
+ * method: "POST",
71
+ * headers: { traceparent: ctx.traceparent },
72
+ * body: JSON.stringify({ trace: event.trajectory }),
73
+ * });
74
+ * },
75
+ * });
76
+ * ```
77
+ */
78
+ export function toW3CTraceContext(event, opts = {}) {
79
+ if (!event.runId)
80
+ return undefined;
81
+ const runHex = uuidToHex(event.runId);
82
+ // The W3C spec is strict about character set and length. If callers
83
+ // pass a non-UUID runId (e.g. from a custom run identifier scheme)
84
+ // bail out rather than emit a malformed header.
85
+ if (runHex.length < 32 || !isPureHex(runHex))
86
+ return undefined;
87
+ let traceIdSource;
88
+ let spanFromFirstHalf;
89
+ if (event.parentRunId) {
90
+ const parentHex = uuidToHex(event.parentRunId);
91
+ if (parentHex.length < 32 || !isPureHex(parentHex)) {
92
+ // Parent is malformed — fall through to runId-only trace. In that
93
+ // case we MUST domain-separate the spanId from the traceId; see
94
+ // the no-parent branch comment below.
95
+ traceIdSource = runHex;
96
+ spanFromFirstHalf = false;
97
+ }
98
+ else {
99
+ // Hierarchical: trace-id from parent, span-id from runId. The
100
+ // first 16 hex of the runId are random in v4 / v7 UUIDs (variant
101
+ // bits live at char 16+), so collision probability per trace is
102
+ // negligible.
103
+ traceIdSource = parentHex;
104
+ spanFromFirstHalf = true;
105
+ }
106
+ }
107
+ else {
108
+ // Top-level invoke: when there is no separate parentRunId, deriving
109
+ // BOTH traceId AND spanId from the FIRST 16 chars of the same UUID
110
+ // produces a `traceparent` where the spanId is a prefix of the
111
+ // traceId. Several OTEL backends (Datadog APM, Honeycomb classic)
112
+ // reject or misroute such spans because they look like self-parents.
113
+ // R1 P0-1 fix (S1235): take the SECOND half of the run hex for the
114
+ // spanId so the two slots are domain-separated even when sourced
115
+ // from the same UUID.
116
+ traceIdSource = runHex;
117
+ spanFromFirstHalf = false;
118
+ }
119
+ const traceId = traceIdSource.slice(0, 32);
120
+ const spanId = spanFromFirstHalf
121
+ ? runHex.slice(0, 16)
122
+ : runHex.slice(16, 32);
123
+ // Spec §3.2.2.2: trace-id == 0...0 is invalid. Same for parent-id.
124
+ if (traceId === ZERO_TRACE_ID || spanId === ZERO_SPAN_ID) {
125
+ return undefined;
126
+ }
127
+ const traceFlags = opts.traceFlags ?? "01";
128
+ return {
129
+ traceparent: `00-${traceId}-${spanId}-${traceFlags}`,
130
+ traceId,
131
+ spanId,
132
+ };
133
+ }
134
+ //# sourceMappingURL=to-w3c-trace-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to-w3c-trace-context.js","sourceRoot":"","sources":["../src/to-w3c-trace-context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Surface 10 (V0.4) — `createTokenBudgetCallbacks(budget, onExceed)`.
3
+ *
4
+ * Production-pattern from the LangGraph TypeScript Production Guide
5
+ * (langgraphjs.guide/production): a token budget enforced per-invocation
6
+ * across ALL LLM calls inside a graph, throwing when the budget is
7
+ * exceeded. Mirrors the canonical example with two differences:
8
+ *
9
+ * 1. Returned as a `BaseCallbackHandler` subclass so it composes with
10
+ * {@link DarwinCallbackHandler} via the standard `{ callbacks: [...] }`
11
+ * option — no model-side patching required, works against any
12
+ * LangChain provider that emits `handleLLMEnd`.
13
+ * 2. Throws a typed {@link DarwinTokenBudgetExceededError} so consumers
14
+ * can `instanceof`-check without parsing message text.
15
+ *
16
+ * The handler tracks BOTH the LangChain-canonical `output.llmOutput.tokenUsage`
17
+ * shape (used by `ChatOpenAI`, `ChatAnthropic`, etc.) AND the per-message
18
+ * usage shape (`generations[0][0].message.usage_metadata`) some providers
19
+ * emit. The total is monotonically non-decreasing across `handleLLMEnd`
20
+ * events; once the budget is crossed the throw happens INSIDE
21
+ * `handleLLMEnd`, which LangChain surfaces back to the caller of
22
+ * `graph.invoke` / `graph.stream`.
23
+ *
24
+ * IMPORTANT: the throw is the only reliable abort signal — LangGraph's
25
+ * node-level retry policy may still re-fire the budget-exceeded path.
26
+ * The `onExceed` callback fires once per handler instance regardless of
27
+ * how many times the throw is observed (use it for logging / alerting,
28
+ * not retry).
29
+ *
30
+ * NEW V0.4 (S1235).
31
+ */
32
+ import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
33
+ import type { LLMResult } from "@langchain/core/outputs";
34
+ /**
35
+ * Options accepted by {@link createTokenBudgetCallbacks}.
36
+ */
37
+ export interface TokenBudgetOptions {
38
+ /**
39
+ * Per-handler-instance token ceiling. Counts the SUM of input + output
40
+ * tokens across every `handleLLMEnd` event. Must be a finite positive
41
+ * integer; invalid values throw `DarwinTokenBudgetExceededError`
42
+ * eagerly on construction so misconfigured deployments fail loud.
43
+ */
44
+ budget: number;
45
+ /**
46
+ * Fire-and-forget side-effect when the budget is exceeded. Receives the
47
+ * cumulative total at the moment of breach, the configured budget, and
48
+ * an optional `providerHint` extracted from the LLMResult (e.g. the
49
+ * model name when emitted). Errors thrown inside this callback are
50
+ * swallowed with a single warn so they cannot mask the budget throw.
51
+ *
52
+ * Use this for logging / metrics / alerting — not for retry.
53
+ */
54
+ onExceed?: (info: TokenBudgetExceedInfo) => void;
55
+ /**
56
+ * Fire on every `handleLLMEnd` event with the running total. Useful for
57
+ * dashboards or step-by-step budget consumption traces. Optional.
58
+ */
59
+ onTick?: (info: TokenBudgetTickInfo) => void;
60
+ }
61
+ export interface TokenBudgetExceedInfo {
62
+ budget: number;
63
+ totalTokens: number;
64
+ providerHint: string | undefined;
65
+ }
66
+ export interface TokenBudgetTickInfo {
67
+ budget: number;
68
+ totalTokens: number;
69
+ deltaTokens: number;
70
+ remainingTokens: number;
71
+ providerHint: string | undefined;
72
+ }
73
+ /**
74
+ * LangChain `BaseCallbackHandler` that enforces a hard token budget
75
+ * across all LLM calls observed during its lifetime.
76
+ *
77
+ * Construct once per `graph.invoke` call (do NOT reuse across requests —
78
+ * the running total is per-handler-instance). The
79
+ * {@link createTokenBudgetCallbacks} factory makes the per-invocation
80
+ * shape ergonomic.
81
+ */
82
+ export declare class TokenBudgetCallbackHandler extends BaseCallbackHandler {
83
+ readonly name = "DarwinTokenBudgetHandler";
84
+ /**
85
+ * V0.4 R1 P2-3 fix (S1235): `awaitHandlers = true` is required so
86
+ * LangChain's callback manager AWAITS this handler before continuing
87
+ * — the synchronous `throw` from `handleLLMEnd` MUST reach the
88
+ * `graph.invoke` caller. With `awaitHandlers = false` the throw may
89
+ * surface as an unhandled rejection in some LangChain versions
90
+ * rather than aborting the graph, which is the entire point of a
91
+ * token budget.
92
+ */
93
+ readonly awaitHandlers = true;
94
+ private readonly budget;
95
+ private readonly onExceed;
96
+ private readonly onTick;
97
+ private totalTokens;
98
+ private exceedWarned;
99
+ private exceedFired;
100
+ private tickErrorWarned;
101
+ constructor(opts: TokenBudgetOptions);
102
+ handleLLMEnd(output: LLMResult): void;
103
+ private warnTick;
104
+ /** Helper for tests + debug introspection. */
105
+ getTotalTokens(): number;
106
+ }
107
+ /**
108
+ * Factory that returns a single-element `BaseCallbackHandler[]` ready to
109
+ * be passed via the standard LangGraph `{ callbacks: [...] }` option.
110
+ * Returning an array is the ergonomic shape — most consumers spread it
111
+ * into a larger callbacks array next to {@link DarwinCallbackHandler}.
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * import {
116
+ * DarwinCallbackHandler,
117
+ * createTokenBudgetCallbacks,
118
+ * DarwinTokenBudgetExceededError,
119
+ * } from "darwin-langgraph";
120
+ *
121
+ * try {
122
+ * const result = await graph.invoke({ task: "..." }, {
123
+ * callbacks: [
124
+ * new DarwinCallbackHandler({ nodeMap, onTrajectory }),
125
+ * ...createTokenBudgetCallbacks({
126
+ * budget: 20_000,
127
+ * onExceed: ({ totalTokens, providerHint }) => {
128
+ * console.error(`Budget breach: ${totalTokens} tok (${providerHint})`);
129
+ * },
130
+ * }),
131
+ * ],
132
+ * });
133
+ * } catch (err) {
134
+ * if (err instanceof DarwinTokenBudgetExceededError) {
135
+ * // ... graceful degradation, fallback model, etc.
136
+ * }
137
+ * }
138
+ * ```
139
+ */
140
+ export declare function createTokenBudgetCallbacks(opts: TokenBudgetOptions): [TokenBudgetCallbackHandler];
141
+ //# sourceMappingURL=token-budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-budget.d.ts","sourceRoot":"","sources":["../src/token-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAIzD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACjD;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AA8DD;;;;;;;;GAQG;AACH,qBAAa,0BAA2B,SAAQ,mBAAmB;IACjE,SAAyB,IAAI,8BAA8B;IAC3D;;;;;;;;OAQG;IACH,SAAyB,aAAa,QAAQ;IAE9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IACtD,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAS;gBAEpB,IAAI,EAAE,kBAAkB;IAyB3B,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAoD9C,OAAO,CAAC,QAAQ;IAUhB,8CAA8C;IACvC,cAAc,IAAI,MAAM;CAGhC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,kBAAkB,GACvB,CAAC,0BAA0B,CAAC,CAE9B"}