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.
- package/CHANGELOG.md +212 -3
- package/README.md +148 -16
- package/dist/darwin-callback-handler.d.ts +134 -0
- package/dist/darwin-callback-handler.d.ts.map +1 -0
- package/dist/darwin-callback-handler.js +261 -0
- package/dist/darwin-callback-handler.js.map +1 -0
- package/dist/darwin-messages-annotation.d.ts +70 -0
- package/dist/darwin-messages-annotation.d.ts.map +1 -0
- package/dist/darwin-messages-annotation.js +78 -0
- package/dist/darwin-messages-annotation.js.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/to-otel-attributes.d.ts +116 -0
- package/dist/to-otel-attributes.d.ts.map +1 -0
- package/dist/to-otel-attributes.js +178 -0
- package/dist/to-otel-attributes.js.map +1 -0
- package/dist/with-darwin-evolution.d.ts +24 -7
- package/dist/with-darwin-evolution.d.ts.map +1 -1
- package/dist/with-darwin-evolution.js +82 -2
- package/dist/with-darwin-evolution.js.map +1 -1
- package/package.json +1 -1
|
@@ -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.
|
|
49
|
+
export declare const VERSION = "0.3.0-alpha.1";
|
|
47
50
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,
|
|
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.
|
|
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,
|
|
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"}
|