darwin-langgraph 0.1.0-alpha.1 → 0.3.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.
@@ -0,0 +1,261 @@
1
+ /**
2
+ * Surface 4 (V0.2) — `DarwinCallbackHandler`.
3
+ *
4
+ * Drop-in replacement for {@link withDarwinEvolution} that uses
5
+ * LangChain's canonical `BaseCallbackHandler` mechanism instead of
6
+ * monkey-patching `graph.invoke` / `graph.stream`. The same trajectory
7
+ * hook fires, the same `nodeMap` routing applies, but the integration
8
+ * is now LangGraph-native — no method overwrites, no concurrent-invoke
9
+ * Set<symbol> dance, no streamMode gymnastics.
10
+ *
11
+ * Usage:
12
+ * ```ts
13
+ * import { DarwinCallbackHandler } from "darwin-langgraph";
14
+ *
15
+ * const handler = new DarwinCallbackHandler({
16
+ * nodeMap: { research: "researcher" },
17
+ * onTrajectory: (event) => {
18
+ * console.log(event.nodeName, event.trajectory.toolCalls.length);
19
+ * },
20
+ * });
21
+ *
22
+ * const result = await graph.invoke(
23
+ * { task: "What is GEPA?" },
24
+ * { callbacks: [handler] },
25
+ * );
26
+ * ```
27
+ *
28
+ * Design notes (S1185 V0.2):
29
+ * - **runId → runName mapping.** LangChain invokes `handleChainStart`
30
+ * with the `runName` arg (the node name in LangGraph's case) and
31
+ * a unique `runId`. We cache that mapping. On `handleChainEnd` we
32
+ * look up the name, find the matching `nodeMap` entry, and dispatch
33
+ * `onTrajectory`.
34
+ * - **Fire-and-forget.** Like the v0.1 monkey-patch wrapper, hook
35
+ * errors are swallowed with one warn-once per handler instance.
36
+ * - **No mutation of LangGraph internals.** This handler never touches
37
+ * `graph.invoke` or `graph.stream` — registering it via the standard
38
+ * `{ callbacks: [...] }` option is the only side effect, which is
39
+ * LangChain's documented integration point (matches Langfuse,
40
+ * Braintrust, LangSmith handler patterns).
41
+ * - **Stream-mode-agnostic.** Works identically with `invoke`,
42
+ * `stream` (any streamMode), and `streamEvents` because the chain
43
+ * callbacks fire regardless of how the consumer iterates.
44
+ * - **Concurrent runs work natively.** LangChain's runId is unique
45
+ * per call — no shared-counter race condition is possible.
46
+ * - **Backwards compat.** `withDarwinEvolution` from v0.1 still works
47
+ * (marked `@deprecated`) and produces the same `DarwinTrajectoryEvent`
48
+ * payload shape. Migration is one line: replace
49
+ * `withDarwinEvolution(graph, opts)` with
50
+ * `graph.invoke(input, { callbacks: [new DarwinCallbackHandler(opts)] })`.
51
+ */
52
+ import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
53
+ import { DarwinEvolutionHookError } from "./errors.js";
54
+ /** Default cap. Aligned with reasonable LangGraph fan-out (~1k nodes / minute). */
55
+ const DEFAULT_MAX_IN_FLIGHT_RUNS = 1024;
56
+ function isExecutionTrace(value) {
57
+ if (!value || typeof value !== "object")
58
+ return false;
59
+ const v = value;
60
+ // R1 V0.2 Critic Finding 2 (S1185): require shape-tightness, not just
61
+ // version. Downstream consumers (e.g. toOtelAttributes) read
62
+ // `toolCalls.length` directly — a malformed trace with missing arrays
63
+ // would crash there. Guard explicitly.
64
+ return (v.version === 1 &&
65
+ Array.isArray(v.toolCalls) &&
66
+ Array.isArray(v.errors));
67
+ }
68
+ function normaliseNodeMap(nodeMap, defaultKey) {
69
+ const resolved = new Map();
70
+ for (const [nodeName, entry] of Object.entries(nodeMap)) {
71
+ if (typeof entry === "string") {
72
+ resolved.set(nodeName, { agentName: entry, trajectoryKey: defaultKey });
73
+ }
74
+ else if (entry !== null &&
75
+ typeof entry === "object" &&
76
+ typeof entry.agentName === "string" &&
77
+ typeof entry.trajectoryKey === "string") {
78
+ resolved.set(nodeName, {
79
+ agentName: entry.agentName,
80
+ trajectoryKey: entry.trajectoryKey,
81
+ });
82
+ }
83
+ else {
84
+ throw new DarwinEvolutionHookError(`DarwinCallbackHandler: nodeMap entry for "${nodeName}" must be a string or ` +
85
+ `{ agentName, trajectoryKey }, got ${typeof entry}.`);
86
+ }
87
+ }
88
+ return resolved;
89
+ }
90
+ /**
91
+ * LangChain `BaseCallbackHandler` that listens for LangGraph node-chain
92
+ * events and dispatches Darwin trajectory hooks. Pass it via the
93
+ * standard `{ callbacks: [...] }` option to any `invoke`/`stream`/`streamEvents`
94
+ * call on a compiled `StateGraph`.
95
+ */
96
+ export class DarwinCallbackHandler extends BaseCallbackHandler {
97
+ name = "DarwinCallbackHandler";
98
+ awaitHandlers = false;
99
+ resolved;
100
+ onTrajectory;
101
+ /**
102
+ * runId → in-flight run state. Map preserves insertion order so the
103
+ * oldest entry is always at `.keys().next().value` for LRU eviction
104
+ * when the cap is exceeded (V0.3 hung-invoke guard).
105
+ */
106
+ runIdToName = new Map();
107
+ maxInFlightRuns;
108
+ warned = false;
109
+ evictionWarned = false;
110
+ constructor(opts) {
111
+ super();
112
+ if (!opts || !opts.nodeMap || Object.keys(opts.nodeMap).length === 0) {
113
+ throw new DarwinEvolutionHookError("DarwinCallbackHandler: opts.nodeMap is required and must contain at least one entry.");
114
+ }
115
+ const defaultKey = opts.defaultTrajectoryKey ?? "darwinTrajectory";
116
+ this.resolved = normaliseNodeMap(opts.nodeMap, defaultKey);
117
+ this.onTrajectory = opts.onTrajectory;
118
+ // V0.3 (S1187): hung-invoke guard. NaN / negative / non-number falls
119
+ // back to default. Infinity disables the cap (opt-out).
120
+ const raw = opts.maxInFlightRuns;
121
+ if (raw === Infinity) {
122
+ this.maxInFlightRuns = Infinity;
123
+ }
124
+ else if (typeof raw === "number" && Number.isFinite(raw) && raw > 0) {
125
+ this.maxInFlightRuns = Math.floor(raw);
126
+ }
127
+ else {
128
+ this.maxInFlightRuns = DEFAULT_MAX_IN_FLIGHT_RUNS;
129
+ }
130
+ }
131
+ /**
132
+ * Capture the run-id → node-name mapping.
133
+ *
134
+ * Implementation note (S1185 V0.2 — live-debug against @langchain/langgraph@1.3.x):
135
+ * `metadata.langgraph_node` is the stable, reliable source for the
136
+ * StateGraph node name. LangGraph populates it on every node-chain
137
+ * invocation. The `runName` parameter slot in `@langchain/core`'s
138
+ * `BaseCallbackHandler` d.ts is undefined for LangGraph chains at
139
+ * runtime — we keep it as a fallback for non-LangGraph chains.
140
+ */
141
+ handleChainStart(_chain, _inputs, runId, _runType, _tags, metadata, runName, parentRunId, _extra) {
142
+ // Primary source: metadata.langgraph_node (set by LangGraph internals).
143
+ let nodeName;
144
+ if (metadata && typeof metadata === "object") {
145
+ const m = metadata;
146
+ if (typeof m["langgraph_node"] === "string") {
147
+ nodeName = m["langgraph_node"];
148
+ }
149
+ }
150
+ // Fallback: runName parameter (for non-LangGraph integrations).
151
+ if (!nodeName && typeof runName === "string" && runName.length > 0) {
152
+ nodeName = runName;
153
+ }
154
+ if (!nodeName)
155
+ return;
156
+ // Only track names that map to a known node. Reduces memory and
157
+ // makes lookup in handleChainEnd a simple `.has()` check.
158
+ if (!this.resolved.has(nodeName))
159
+ return;
160
+ // V0.3 (S1187): hung-invoke guard. If we are about to exceed the cap
161
+ // AND the runId is genuinely new (not a re-fire), evict the oldest
162
+ // entry. Map iteration order is insertion order — the first key is
163
+ // the oldest. Warn once per handler instance so a real leak shows up
164
+ // in logs without spamming.
165
+ if (this.maxInFlightRuns !== Infinity &&
166
+ !this.runIdToName.has(runId) &&
167
+ this.runIdToName.size >= this.maxInFlightRuns) {
168
+ const oldest = this.runIdToName.keys().next().value;
169
+ if (oldest !== undefined) {
170
+ this.runIdToName.delete(oldest);
171
+ }
172
+ if (!this.evictionWarned) {
173
+ this.evictionWarned = true;
174
+ console.warn(`[darwin-langgraph] DarwinCallbackHandler: in-flight runs exceeded ` +
175
+ `${this.maxInFlightRuns} — evicting oldest entry. This usually ` +
176
+ `means handleChainEnd / handleChainError did not fire for some ` +
177
+ `runs (worker crash, parent invoke aborted mid-flight, or ` +
178
+ `LangGraph internal bug). Subsequent evictions are silent.`);
179
+ }
180
+ }
181
+ this.runIdToName.set(runId, {
182
+ nodeName,
183
+ parentRunId: typeof parentRunId === "string" ? parentRunId : undefined,
184
+ });
185
+ }
186
+ /**
187
+ * When a node-chain finishes, look up its name, locate the matching
188
+ * trajectory in `outputs`, and dispatch onTrajectory.
189
+ *
190
+ * `outputs` carries the state update the node returned — which may be
191
+ * a partial state (just the new keys). When the node was wrapped via
192
+ * {@link createDarwinNode}, the trajectoryKey lives directly on that
193
+ * partial state under its configured name.
194
+ */
195
+ handleChainEnd(outputs, runId, _parentRunId, _tags, _kwargs) {
196
+ const inFlight = this.runIdToName.get(runId);
197
+ if (!inFlight)
198
+ return;
199
+ // One-shot cleanup of the mapping so completed runs don't leak.
200
+ // R1 V0.2 Critic Finding 1 (S1185): the `runIdToName.delete` here
201
+ // is the ONLY dedup we need — LangGraph guarantees `handleChainEnd`
202
+ // fires exactly once per `runId`, and after deletion any second
203
+ // call returns early at `if (!inFlight)`. The pre-V0.2 `firedRuns`
204
+ // Set was redundant AND leaked unbounded — removed.
205
+ this.runIdToName.delete(runId);
206
+ if (!this.onTrajectory)
207
+ return;
208
+ const entry = this.resolved.get(inFlight.nodeName);
209
+ if (!entry)
210
+ return;
211
+ if (outputs === null || typeof outputs !== "object")
212
+ return;
213
+ const trajectory = outputs[entry.trajectoryKey];
214
+ if (!isExecutionTrace(trajectory))
215
+ return;
216
+ const frozen = Object.freeze({ ...outputs });
217
+ // V0.3 (S1187): propagate runId + parentRunId so OTEL exporters,
218
+ // Langfuse, LangSmith, etc. can rebuild the span hierarchy from the
219
+ // event payload alone (no separate runId-tracking side-channel).
220
+ const event = {
221
+ nodeName: inFlight.nodeName,
222
+ agentName: entry.agentName,
223
+ trajectory,
224
+ finalState: frozen,
225
+ runId,
226
+ ...(inFlight.parentRunId !== undefined ? { parentRunId: inFlight.parentRunId } : {}),
227
+ };
228
+ // Fire-and-forget. The handler base class supports async returns
229
+ // but we don't want to block the chain end on slow user callbacks.
230
+ void Promise.resolve()
231
+ .then(() => this.onTrajectory(event))
232
+ .catch((err) => this.swallow(err));
233
+ }
234
+ /**
235
+ * Forget the in-flight runId when a chain errors out. We don't fire
236
+ * the hook on error — the trajectory is by definition incomplete.
237
+ */
238
+ handleChainError(_err, runId, _parentRunId) {
239
+ this.runIdToName.delete(runId);
240
+ }
241
+ swallow(err) {
242
+ // R1 V0.2 Critic Finding 5 (S1185): do NOT short-circuit on falsy
243
+ // `err` — `throw 0` / `throw ""` / `throw null` from user callbacks
244
+ // should still surface in logs (silent-failure is worse than noisy).
245
+ if (this.warned)
246
+ return;
247
+ this.warned = true;
248
+ console.warn(`[darwin-langgraph] DarwinCallbackHandler.onTrajectory threw — swallowed. ` +
249
+ `Subsequent throws will be silent. Original error: ` +
250
+ `${err instanceof Error ? err.message : String(err)}`);
251
+ }
252
+ /**
253
+ * Helper for tests + debug introspection — returns how many in-flight
254
+ * chain runs we are currently tracking. Should be 0 between
255
+ * top-level invocations.
256
+ */
257
+ getInFlightCount() {
258
+ return this.runIdToName.size;
259
+ }
260
+ }
261
+ //# sourceMappingURL=darwin-callback-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"darwin-callback-handler.js","sourceRoot":"","sources":["../src/darwin-callback-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Surface 6 (V0.2) — `darwinMessagesAnnotation(extra?)`.
3
+ *
4
+ * Variant of {@link darwinAnnotation} that also includes LangGraph's
5
+ * canonical `messages` channel (using `messagesStateReducer` from
6
+ * `@langchain/langgraph`). Use this when your graph mixes Darwin agents
7
+ * with `createReactAgent` / `MessagesAnnotation`-based prebuilt agents
8
+ * — they all read and write the same `messages` channel without
9
+ * channel-name conflicts.
10
+ *
11
+ * Layered channels:
12
+ * - `task` (string, last-write-wins) — Darwin agent task input
13
+ * - `output` (string, last-write-wins) — Darwin agent text output
14
+ * - `darwinTrajectory` (ExecutionTrace | undefined) — captured trace
15
+ * - `messages` (BaseMessage[], `messagesStateReducer`) — chat history
16
+ *
17
+ * Composable: any `extra` channels merge in.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * import { darwinMessagesAnnotation, createDarwinNode } from "darwin-langgraph";
22
+ * import { StateGraph } from "@langchain/langgraph";
23
+ * import { createReactAgent } from "@langchain/langgraph/prebuilt";
24
+ * import { ChatAnthropic } from "@langchain/anthropic";
25
+ *
26
+ * const State = darwinMessagesAnnotation();
27
+ *
28
+ * const planner = createReactAgent({
29
+ * llm: new ChatAnthropic({ model: "claude-haiku-4-5" }),
30
+ * tools: [],
31
+ * });
32
+ *
33
+ * const graph = new StateGraph(State)
34
+ * .addNode("plan", planner) // writes to messages
35
+ * .addNode("execute", createDarwinNode(myAgent)) // writes to output
36
+ * .addEdge("__start__", "plan")
37
+ * .addEdge("plan", "execute")
38
+ * .compile();
39
+ * ```
40
+ *
41
+ * Design notes:
42
+ * - **Same inference quirk as `darwinAnnotation`.** Return type is
43
+ * inferred from `Annotation.Root`; the internal `LastValue` vs
44
+ * `BaseChannel` union is opaque to it. Hand-typing triggers TS2741.
45
+ * - **`messages` default is `[]`** — graphs that don't seed messages
46
+ * in `invoke({ task: "..." })` still work.
47
+ */
48
+ import type { BaseMessage } from "@langchain/core/messages";
49
+ /**
50
+ * Spec for the `messages` channel — re-exported for power-users who want
51
+ * to spread it into their own `Annotation.Root` call manually.
52
+ *
53
+ * Return type inferred (same `LastValue<T>` vs `BaseChannel<T>` quirk
54
+ * documented on `getDarwinChannelSpec` — hand-typing triggers TS2741).
55
+ */
56
+ export declare function getMessagesChannelSpec(): {
57
+ messages: import("@langchain/langgraph").BaseChannel<BaseMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>, import("@langchain/core/messages").MessageType>[], BaseMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>, import("@langchain/core/messages").MessageType>[] | import("@langchain/langgraph").OverwriteValue<BaseMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>, import("@langchain/core/messages").MessageType>[]>, unknown>;
58
+ };
59
+ /**
60
+ * Build an `Annotation.Root` with the three Darwin channels PLUS the
61
+ * canonical `messages` channel for interop with `createReactAgent` /
62
+ * `MessagesAnnotation`-based prebuilt agents.
63
+ */
64
+ export declare function darwinMessagesAnnotation<Extra extends Record<string, any> = {}>(extra?: Extra): import("@langchain/langgraph").AnnotationRoot<{
65
+ messages: import("@langchain/langgraph").BaseChannel<BaseMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>, import("@langchain/core/messages").MessageType>[], BaseMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>, import("@langchain/core/messages").MessageType>[] | import("@langchain/langgraph").OverwriteValue<BaseMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>, import("@langchain/core/messages").MessageType>[]>, unknown>;
66
+ task: import("@langchain/langgraph").LastValue<string>;
67
+ output: import("@langchain/langgraph").LastValue<string>;
68
+ darwinTrajectory: import("@langchain/langgraph").BaseChannel<import("darwin-agents").ExecutionTrace | undefined, import("darwin-agents").ExecutionTrace | import("@langchain/langgraph").OverwriteValue<import("darwin-agents").ExecutionTrace | undefined> | undefined, unknown>;
69
+ } & Extra>;
70
+ //# sourceMappingURL=darwin-messages-annotation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"darwin-messages-annotation.d.ts","sourceRoot":"","sources":["../src/darwin-messages-annotation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAI5D;;;;;;GAMG;AACH,wBAAgB,sBAAsB;;EAOrC;AAED;;;;GAIG;AAEH,wBAAgB,wBAAwB,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,EAC7E,KAAK,CAAC,EAAE,KAAK;;;;;WAOd"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Surface 6 (V0.2) — `darwinMessagesAnnotation(extra?)`.
3
+ *
4
+ * Variant of {@link darwinAnnotation} that also includes LangGraph's
5
+ * canonical `messages` channel (using `messagesStateReducer` from
6
+ * `@langchain/langgraph`). Use this when your graph mixes Darwin agents
7
+ * with `createReactAgent` / `MessagesAnnotation`-based prebuilt agents
8
+ * — they all read and write the same `messages` channel without
9
+ * channel-name conflicts.
10
+ *
11
+ * Layered channels:
12
+ * - `task` (string, last-write-wins) — Darwin agent task input
13
+ * - `output` (string, last-write-wins) — Darwin agent text output
14
+ * - `darwinTrajectory` (ExecutionTrace | undefined) — captured trace
15
+ * - `messages` (BaseMessage[], `messagesStateReducer`) — chat history
16
+ *
17
+ * Composable: any `extra` channels merge in.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * import { darwinMessagesAnnotation, createDarwinNode } from "darwin-langgraph";
22
+ * import { StateGraph } from "@langchain/langgraph";
23
+ * import { createReactAgent } from "@langchain/langgraph/prebuilt";
24
+ * import { ChatAnthropic } from "@langchain/anthropic";
25
+ *
26
+ * const State = darwinMessagesAnnotation();
27
+ *
28
+ * const planner = createReactAgent({
29
+ * llm: new ChatAnthropic({ model: "claude-haiku-4-5" }),
30
+ * tools: [],
31
+ * });
32
+ *
33
+ * const graph = new StateGraph(State)
34
+ * .addNode("plan", planner) // writes to messages
35
+ * .addNode("execute", createDarwinNode(myAgent)) // writes to output
36
+ * .addEdge("__start__", "plan")
37
+ * .addEdge("plan", "execute")
38
+ * .compile();
39
+ * ```
40
+ *
41
+ * Design notes:
42
+ * - **Same inference quirk as `darwinAnnotation`.** Return type is
43
+ * inferred from `Annotation.Root`; the internal `LastValue` vs
44
+ * `BaseChannel` union is opaque to it. Hand-typing triggers TS2741.
45
+ * - **`messages` default is `[]`** — graphs that don't seed messages
46
+ * in `invoke({ task: "..." })` still work.
47
+ */
48
+ import { Annotation, messagesStateReducer, } from "@langchain/langgraph";
49
+ import { getDarwinChannelSpec } from "./darwin-annotation.js";
50
+ /**
51
+ * Spec for the `messages` channel — re-exported for power-users who want
52
+ * to spread it into their own `Annotation.Root` call manually.
53
+ *
54
+ * Return type inferred (same `LastValue<T>` vs `BaseChannel<T>` quirk
55
+ * documented on `getDarwinChannelSpec` — hand-typing triggers TS2741).
56
+ */
57
+ export function getMessagesChannelSpec() {
58
+ return {
59
+ messages: Annotation({
60
+ reducer: messagesStateReducer,
61
+ default: () => [],
62
+ }),
63
+ };
64
+ }
65
+ /**
66
+ * Build an `Annotation.Root` with the three Darwin channels PLUS the
67
+ * canonical `messages` channel for interop with `createReactAgent` /
68
+ * `MessagesAnnotation`-based prebuilt agents.
69
+ */
70
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
71
+ export function darwinMessagesAnnotation(extra) {
72
+ return Annotation.Root({
73
+ ...getDarwinChannelSpec(),
74
+ ...getMessagesChannelSpec(),
75
+ ...(extra ?? {}),
76
+ });
77
+ }
78
+ //# sourceMappingURL=darwin-messages-annotation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"darwin-messages-annotation.js","sourceRoot":"","sources":["../src/darwin-messages-annotation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,EACL,UAAU,EACV,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,QAAQ,EAAE,UAAU,CAAgB;YAClC,OAAO,EAAE,oBAAoB;YAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;SAClB,CAAC;KACH,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,8DAA8D;AAC9D,MAAM,UAAU,wBAAwB,CACtC,KAAa;IAEb,OAAO,UAAU,CAAC,IAAI,CAAC;QACrB,GAAG,oBAAoB,EAAE;QACzB,GAAG,sBAAsB,EAAE;QAC3B,GAAG,CAAC,KAAK,IAAK,EAAY,CAAC;KAC5B,CAAC,CAAC;AACL,CAAC"}
package/dist/index.d.ts CHANGED
@@ -37,11 +37,14 @@
37
37
  * console.log(result.output);
38
38
  * ```
39
39
  */
40
- export { createDarwinNode, type CreateDarwinNodeOptions, type DarwinNodeFn, } from "./create-darwin-node.js";
40
+ export { createDarwinNode, type CreateDarwinNodeOptions, type DarwinNodeFn, type DarwinRunOptionsPassthrough, } from "./create-darwin-node.js";
41
41
  export { darwinAnnotation, getDarwinChannelSpec, lastWriteWinsTrajectoryReducer, } from "./darwin-annotation.js";
42
42
  export { withDarwinEvolution, type DarwinEvolutionOptions, type DarwinNodeMapEntry, type DarwinTrajectoryEvent, } from "./with-darwin-evolution.js";
43
+ export { DarwinCallbackHandler, type DarwinCallbackHandlerOptions, } from "./darwin-callback-handler.js";
44
+ export { toOtelAttributes, toolCallToOtelAttributes, type OtelAttributes, type ToOtelAttributesOptions, type ToolCallOtelOptions, } from "./to-otel-attributes.js";
45
+ export { darwinMessagesAnnotation, getMessagesChannelSpec, } from "./darwin-messages-annotation.js";
43
46
  export { DarwinNodeError, DarwinEvolutionHookError } from "./errors.js";
44
47
  export type { AgentDefinition, DarwinExperiment, ExecutionTrace, MemoryProvider, RunResult, TraceToolCall, TraceTokenUsage, TraceTurnError, } from "./types.js";
45
48
  /** Adapter version — sync with `package.json` on every release. */
46
- export declare const VERSION = "0.1.0-alpha.1";
49
+ export declare const VERSION = "0.3.0-alpha.1";
47
50
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,YAAY,GAClB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,8BAA8B,GAC/B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,GAC3B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAExE,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,SAAS,EACT,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,mEAAmE;AACnE,eAAO,MAAM,OAAO,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,2BAA2B,GACjC,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,8BAA8B,GAC/B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,GAC3B,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,qBAAqB,EACrB,KAAK,4BAA4B,GAClC,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EACL,gBAAgB,EAChB,wBAAwB,EACxB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,GACzB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAExE,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,SAAS,EACT,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,mEAAmE;AACnE,eAAO,MAAM,OAAO,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -40,7 +40,13 @@
40
40
  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
+ // V0.2 — LangChain-native callback handler (preferred over `withDarwinEvolution`)
44
+ export { DarwinCallbackHandler, } from "./darwin-callback-handler.js";
45
+ // V0.2 — OTEL GenAI Semantic Conventions mapping
46
+ export { toOtelAttributes, toolCallToOtelAttributes, } from "./to-otel-attributes.js";
47
+ // V0.2 — MessagesAnnotation interop for graphs mixing createReactAgent + createDarwinNode
48
+ export { darwinMessagesAnnotation, getMessagesChannelSpec, } from "./darwin-messages-annotation.js";
43
49
  export { DarwinNodeError, DarwinEvolutionHookError } from "./errors.js";
44
50
  /** Adapter version — sync with `package.json` on every release. */
45
- export const VERSION = "0.1.0-alpha.1";
51
+ export const VERSION = "0.3.0-alpha.1";
46
52
  //# 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,GAGjB,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,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,OAAO,EACL,qBAAqB,GAEtB,MAAM,8BAA8B,CAAC;AAEtC,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"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Surface 5 (V0.2) — `toOtelAttributes(trajectory, opts?)`.
3
+ *
4
+ * Pure mapper from Darwin's `ExecutionTrace` to a flat
5
+ * `Record<string, string | number | boolean>` keyed by
6
+ * [OpenTelemetry GenAI Semantic Conventions](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/gen-ai-spans.md)
7
+ * attribute names — so any OTEL-compatible exporter (Langfuse,
8
+ * Braintrust, Honeycomb, Datadog, New Relic, Grafana) picks up the
9
+ * trace data without further mapping.
10
+ *
11
+ * Coverage:
12
+ * - `gen_ai.operation.name` = `"invoke_agent"` (constant per OTEL
13
+ * GenAI spec for agent-level operations).
14
+ * - `gen_ai.agent.name` = `opts.agentName` (callers passes the
15
+ * agent's logical name).
16
+ * - `gen_ai.agent.id` = `opts.agentId` (optional UUID/run id).
17
+ * - `gen_ai.usage.input_tokens` / `output_tokens` / `cache_read_tokens` /
18
+ * `cache_creation_tokens` — only emitted when the upstream
19
+ * trajectory captured token usage (i.e. provider reported it).
20
+ * - `darwin.trajectory.tool_calls.count` (custom, non-OTEL — namespaced
21
+ * under `darwin.*` to avoid colliding with future OTEL fields).
22
+ * - `darwin.trajectory.text_blocks` / `turns` / `mcp_invocations` /
23
+ * `errors.count` — same custom namespace.
24
+ * - `darwin.trajectory.captured_at` — ISO string for traceability.
25
+ *
26
+ * Per OTEL GenAI spec we DO NOT emit `gen_ai.tool.call.arguments` /
27
+ * `gen_ai.tool.call.result` here — those are span-level attributes
28
+ * meant to be attached to per-tool-call spans, not the aggregate
29
+ * trajectory. Callers who need them should iterate `trajectory.toolCalls`
30
+ * and emit one child span per call.
31
+ *
32
+ * Design notes:
33
+ * - **Sparse output.** Undefined fields stay out of the result rather
34
+ * than appearing as `null` — keeps OTEL exporters from over-counting
35
+ * missing-data buckets.
36
+ * - **No allocation on hot path.** The function builds a single
37
+ * object literal incrementally; no Map / Set / array intermediates.
38
+ * - **Pure.** No side effects, no I/O, no Date.now() — fully
39
+ * testable with deterministic inputs.
40
+ */
41
+ import type { ExecutionTrace } from "darwin-agents";
42
+ /** Options accepted by {@link toOtelAttributes}. */
43
+ export interface ToOtelAttributesOptions {
44
+ /** Logical agent name. Maps to `gen_ai.agent.name`. */
45
+ agentName?: string;
46
+ /** Optional agent id (e.g. uuid or experiment id). Maps to `gen_ai.agent.id`. */
47
+ agentId?: string;
48
+ /**
49
+ * Custom namespace for Darwin-specific attributes that have no OTEL
50
+ * equivalent. Default: `"darwin"` → emits `darwin.trajectory.*`.
51
+ * Override for organisation-wide naming conventions (e.g. `"company.darwin"`).
52
+ */
53
+ customNamespace?: string;
54
+ }
55
+ /** Flat attribute bag matching OTEL's primitive-only attribute types. */
56
+ export type OtelAttributes = Record<string, string | number | boolean>;
57
+ /**
58
+ * Build the OTEL attribute bag for an `ExecutionTrace`.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * import { toOtelAttributes } from "darwin-langgraph";
63
+ *
64
+ * const attrs = toOtelAttributes(event.trajectory, {
65
+ * agentName: event.agentName,
66
+ * agentId: someExperimentId,
67
+ * });
68
+ * // attrs = {
69
+ * // "gen_ai.operation.name": "invoke_agent",
70
+ * // "gen_ai.agent.name": "researcher",
71
+ * // "gen_ai.agent.id": "exp-2026-05-25-001",
72
+ * // "gen_ai.usage.input_tokens": 1200,
73
+ * // "gen_ai.usage.output_tokens": 340,
74
+ * // "darwin.trajectory.tool_calls.count": 3,
75
+ * // "darwin.trajectory.text_blocks": 2,
76
+ * // "darwin.trajectory.turns": 4,
77
+ * // "darwin.trajectory.mcp_invocations": 2,
78
+ * // "darwin.trajectory.errors.count": 0,
79
+ * // "darwin.trajectory.captured_at": "2026-05-25T08:00:00.000Z",
80
+ * // }
81
+ *
82
+ * // OTEL exporter usage (any tracer):
83
+ * span.setAttributes(attrs);
84
+ * ```
85
+ */
86
+ export declare function toOtelAttributes(trajectory: ExecutionTrace, opts?: ToOtelAttributesOptions): OtelAttributes;
87
+ /**
88
+ * Build per-tool-call OTEL attributes for each entry in
89
+ * `trajectory.toolCalls`. Use this to emit one child span per tool call
90
+ * under the parent agent span.
91
+ *
92
+ * Coverage:
93
+ * - `gen_ai.operation.name` = `"execute_tool"` (OTEL spec).
94
+ * - `gen_ai.tool.name` (OTEL spec).
95
+ * - `gen_ai.tool.call.id` (OTEL spec).
96
+ * - `gen_ai.tool.type` = `"function"` (default for MCP + builtins).
97
+ * - `darwin.tool.outcome` = `"success" | "error"` (custom).
98
+ * - `darwin.tool.duration_ms` (custom).
99
+ * - `darwin.tool.turn` (custom).
100
+ * - `darwin.tool.is_mcp` (boolean, custom).
101
+ * - `gen_ai.tool.call.arguments` (JSON-stringified) — opt-in via
102
+ * `opts.includeArguments`. Per OTEL spec this is OPT-IN because args
103
+ * can contain sensitive data.
104
+ * - `gen_ai.tool.call.result` — opt-in via `opts.includeResults` for
105
+ * the same reason.
106
+ * - `error.type` = `trajectory.toolCalls[i].errorClass` (when outcome=error).
107
+ */
108
+ export interface ToolCallOtelOptions {
109
+ customNamespace?: string;
110
+ /** Emit `gen_ai.tool.call.arguments` (OPT-IN, may contain PII). */
111
+ includeArguments?: boolean;
112
+ /** Emit `gen_ai.tool.call.result` (OPT-IN, may contain PII). */
113
+ includeResults?: boolean;
114
+ }
115
+ export declare function toolCallToOtelAttributes(call: ExecutionTrace["toolCalls"][number], opts?: ToolCallOtelOptions): OtelAttributes;
116
+ //# sourceMappingURL=to-otel-attributes.d.ts.map
@@ -0,0 +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"}