@cendor/core 0.3.2 → 0.4.0

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,345 @@
1
+ /**
2
+ * Optional LangChain.js / LangGraph integration — the SDK-aligned way to observe a framework.
3
+ *
4
+ * The SDK-aligned integration point for a framework is its **callback system**, not client
5
+ * monkeypatching: `@langchain/openai` consumes usage through its own response path and streams via
6
+ * async iterators, so `instrument()` on the raw client can miss usage — observing through callbacks
7
+ * sidesteps that. {@link CendorCallbackHandler} reads LangChain's own `usage_metadata` (which carries
8
+ * **reasoning** and **cached** token breakdowns), prices the call offline, correlates multi-node /
9
+ * multi-agent runs via `traceId`, and emits normalized {@link LLMCall} / {@link ToolCall} events on
10
+ * the bus — so `tokenguard`, `acttrace`, and any other subscriber see LangChain activity with no
11
+ * client touch.
12
+ *
13
+ * **Recording-only.** This path is post-call: it *observes*, it never enforces. `tokenguard`'s caps
14
+ * and `acttrace`'s `guard()` act on the `instrument()` seam, which the callback path does not touch —
15
+ * so pre-flight enforcement (budget blocking, redact-before-send) is a **no-op** here. Use the direct
16
+ * provider SDK with `instrument()` when you need enforcement.
17
+ *
18
+ * Requires the optional peer dependency, keeping `@cendor/core` dependency-light (like
19
+ * `@opentelemetry/api`). Importing this subpath without `@langchain/core` installed throws a clear
20
+ * error.
21
+ *
22
+ * npm install @langchain/core
23
+ *
24
+ * Usage:
25
+ *
26
+ * ```ts
27
+ * import { CendorCallbackHandler } from '@cendor/core/langchain';
28
+ * const handler = new CendorCallbackHandler();
29
+ *
30
+ * const llm = new ChatOpenAI({ model: 'gpt-4o', callbacks: [handler] }); // every call recorded
31
+ * await llm.invoke('hi');
32
+ *
33
+ * // or per-call / per-agent — propagates to all LangGraph nodes, correlated by root run:
34
+ * await agent.invoke({ messages: [...] }, { callbacks: [handler] });
35
+ * ```
36
+ */
37
+ import { createRequire } from 'node:module';
38
+ import * as bus from './bus.js';
39
+ import * as prices from './prices.js';
40
+ import { LLMCall, ToolCall, Usage } from './types.js';
41
+ /**
42
+ * Load LangChain's `BaseCallbackHandler` synchronously so this class can extend it, mirroring the
43
+ * Python handler's import-time `ImportError` when the optional dependency is absent. LangChain
44
+ * accepts handlers by duck-typing (`copy`/`name`/`awaitHandlers`), so the CJS build resolved here
45
+ * interoperates with an ESM-imported `@langchain/core` in the host app.
46
+ */
47
+ function loadBaseCallbackHandler() {
48
+ try {
49
+ const req = createRequire(import.meta.url);
50
+ const mod = req('@langchain/core/callbacks/base');
51
+ return mod.BaseCallbackHandler;
52
+ }
53
+ catch (cause) {
54
+ throw new Error('@cendor/core/langchain requires @langchain/core. Install it with: npm install @langchain/core', { cause });
55
+ }
56
+ }
57
+ const BaseCallbackHandler = loadBaseCallbackHandler();
58
+ /**
59
+ * A LangChain / LangGraph callback handler that records usage, reasoning, tool calls, and run
60
+ * correlation onto cendor's bus. **Recording-only** — never enforces (see the module docstring).
61
+ *
62
+ * Attach it globally (`new ChatOpenAI({ callbacks: [new CendorCallbackHandler()] })`), per call
63
+ * (`{ callbacks: [handler] }`), or on an agent (`agent.invoke(..., { callbacks: [handler] })`) — for
64
+ * LangGraph it propagates to every node and its tools.
65
+ *
66
+ * **Correlation.** Every emitted event carries a `traceId` that is the **root run id** of the
67
+ * invocation — resolved by tracking the callback run tree (each run's `parentRunId`) and walking to
68
+ * the top. So all model/tool calls of one `agent.invoke` (across its nodes and the react loop) share
69
+ * one `traceId`, while separate invocations get distinct ones. A standalone `llm.invoke` uses its own
70
+ * run id. This is a correlation *hook*, not an orchestrator: cendor groups by the framework's own run
71
+ * tree; it invents no run graph.
72
+ *
73
+ * Every handler body is exception-safe (a recorder must never break the app); `raiseError` is left
74
+ * `false` (the base default) so LangChain also swallows any escape.
75
+ */
76
+ export class CendorCallbackHandler extends BaseCallbackHandler {
77
+ name = 'CendorCallbackHandler';
78
+ // runId -> parentRunId (or null for a root), built from the *Start callbacks so each event can be
79
+ // resolved to the root run it belongs to. Bounded: entries are removed on run end/error.
80
+ parents = new Map();
81
+ // tool runId -> pending { name, input }, bridged from handleToolStart to handleToolEnd.
82
+ toolRuns = new Map();
83
+ // Node is single-threaded, so — unlike the Python handler — there is no lock guarding the maps.
84
+ /**
85
+ * Share one handler instance across merged callback managers instead of copying. A stateful
86
+ * correlation handler must observe the *whole* run tree; the base `copy()` returns a fresh clone
87
+ * with empty maps, which would break trace-id resolution. Sharing is safe here: every handler body
88
+ * is exception-safe and the map operations are idempotent, and returning the same identity also
89
+ * lets LangChain's identity-based handler de-duplication work.
90
+ */
91
+ copy() {
92
+ return this;
93
+ }
94
+ // ------------------------------------------------------------------ run-tree bookkeeping
95
+ register(runId, parentRunId) {
96
+ if (!runId)
97
+ return;
98
+ this.parents.set(runId, parentRunId ?? null);
99
+ }
100
+ forget(runId) {
101
+ if (!runId)
102
+ return;
103
+ this.parents.delete(runId);
104
+ }
105
+ /**
106
+ * The root run id for this event: walk `parent` links up to the top. Falls back to
107
+ * `parentRunId`/`runId` when the run tree wasn't observed (e.g. a bare model call).
108
+ */
109
+ traceId(runId, parentRunId) {
110
+ let rid = runId ?? '';
111
+ if (!rid)
112
+ return parentRunId ?? '';
113
+ const seen = new Set();
114
+ while (this.parents.has(rid) && this.parents.get(rid) && !seen.has(rid)) {
115
+ seen.add(rid);
116
+ rid = this.parents.get(rid); // guarded truthy above
117
+ }
118
+ return rid;
119
+ }
120
+ handleChainStart(_chain, _inputs, runId, _runType, _tags, _metadata, _runName, parentRunId) {
121
+ this.register(runId, parentRunId);
122
+ }
123
+ handleChainEnd(_outputs, runId) {
124
+ this.forget(runId);
125
+ }
126
+ handleChainError(_err, runId) {
127
+ this.forget(runId);
128
+ }
129
+ handleChatModelStart(_llm, _messages, runId, parentRunId) {
130
+ this.register(runId, parentRunId);
131
+ }
132
+ handleLLMStart(_llm, _prompts, runId, parentRunId) {
133
+ this.register(runId, parentRunId);
134
+ }
135
+ // ------------------------------------------------------------------ LLM calls
136
+ /** Emit an {@link LLMCall} with usage/reasoning/cost and a run-correlated `traceId`. */
137
+ handleLLMEnd(output, runId, parentRunId) {
138
+ try {
139
+ const usage = usageFromResult(output);
140
+ const call = new LLMCall({
141
+ id: uuidHex(),
142
+ provider: 'langchain', // observed via the framework; the real model rides call.model
143
+ model: modelFromResult(output),
144
+ messages: [], // the callback path is usage-focused; prompts aren't recorded here
145
+ usage,
146
+ traceId: this.traceId(runId, parentRunId),
147
+ });
148
+ call.metadata.source = 'langchain';
149
+ setCost(call, usage);
150
+ bus.emit(call);
151
+ }
152
+ catch {
153
+ // recording must never break the app
154
+ }
155
+ finally {
156
+ this.forget(runId);
157
+ }
158
+ }
159
+ /** Record a failed model call (no usage) with the error on metadata — never re-raised. */
160
+ handleLLMError(err, runId, parentRunId) {
161
+ try {
162
+ const call = new LLMCall({
163
+ id: uuidHex(),
164
+ provider: 'langchain',
165
+ model: '',
166
+ messages: [],
167
+ traceId: this.traceId(runId, parentRunId),
168
+ });
169
+ call.metadata.source = 'langchain';
170
+ call.metadata.error = errorMessage(err);
171
+ bus.emit(call);
172
+ }
173
+ catch {
174
+ // recording must never break the app
175
+ }
176
+ finally {
177
+ this.forget(runId);
178
+ }
179
+ }
180
+ // ------------------------------------------------------------------ tool calls
181
+ /** Record the tool's parent (for correlation) and stash its name/args until it ends. */
182
+ handleToolStart(tool, input, runId, parentRunId) {
183
+ this.register(runId, parentRunId);
184
+ try {
185
+ this.toolRuns.set(runId, { name: serializedName(tool) ?? 'tool', input });
186
+ }
187
+ catch {
188
+ // recording must never break the app
189
+ }
190
+ }
191
+ /** Emit a {@link ToolCall} (name, args, result) correlated to its run's root. */
192
+ handleToolEnd(output, runId, parentRunId) {
193
+ try {
194
+ const pending = this.toolRuns.get(runId);
195
+ this.toolRuns.delete(runId);
196
+ const tc = new ToolCall({
197
+ id: uuidHex(),
198
+ name: pending?.name ?? 'tool',
199
+ arguments: { input: pending?.input },
200
+ result: output,
201
+ traceId: this.traceId(runId, parentRunId),
202
+ });
203
+ tc.metadata.source = 'langchain';
204
+ bus.emit(tc);
205
+ }
206
+ catch {
207
+ // recording must never break the app
208
+ }
209
+ finally {
210
+ this.forget(runId);
211
+ }
212
+ }
213
+ /** Emit a {@link ToolCall} marking the failure; drop the pending entry. Never re-raised. */
214
+ handleToolError(err, runId, parentRunId) {
215
+ try {
216
+ const pending = this.toolRuns.get(runId);
217
+ this.toolRuns.delete(runId);
218
+ const tc = new ToolCall({
219
+ id: uuidHex(),
220
+ name: pending?.name ?? 'tool',
221
+ arguments: { input: pending?.input },
222
+ traceId: this.traceId(runId, parentRunId),
223
+ });
224
+ tc.metadata.source = 'langchain';
225
+ tc.metadata.error = errorMessage(err);
226
+ bus.emit(tc);
227
+ }
228
+ catch {
229
+ // recording must never break the app
230
+ }
231
+ finally {
232
+ this.forget(runId);
233
+ }
234
+ }
235
+ }
236
+ // --------------------------------------------------------------------------- extraction helpers
237
+ /** A hex UUID (no dashes), mirroring the ids `instrument()` stamps. */
238
+ function uuidHex() {
239
+ return globalThis.crypto.randomUUID().replace(/-/g, '');
240
+ }
241
+ function num(value) {
242
+ if (typeof value === 'number')
243
+ return Number.isFinite(value) ? value : 0;
244
+ if (typeof value === 'string') {
245
+ const n = Number.parseInt(value, 10);
246
+ return Number.isNaN(n) ? 0 : n;
247
+ }
248
+ return 0;
249
+ }
250
+ /**
251
+ * Recover usage from an `LLMResult`: prefer a generation message's `usage_metadata` (it carries
252
+ * reasoning + cache breakdowns), falling back to `llmOutput`'s token usage.
253
+ */
254
+ function usageFromResult(result) {
255
+ for (const gens of result.generations ?? []) {
256
+ for (const gen of gens) {
257
+ const meta = gen.message?.usage_metadata;
258
+ if (meta)
259
+ return usageFromMetadata(meta);
260
+ }
261
+ }
262
+ const llmOutput = (result.llmOutput ?? {});
263
+ const tokenUsage = (llmOutput.tokenUsage ?? llmOutput.token_usage ?? llmOutput.usage);
264
+ if (tokenUsage) {
265
+ const inp = num(tokenUsage.promptTokens ?? tokenUsage.prompt_tokens ?? tokenUsage.input_tokens);
266
+ const out = num(tokenUsage.completionTokens ?? tokenUsage.completion_tokens ?? tokenUsage.output_tokens);
267
+ const cdetails = (tokenUsage.completion_tokens_details ??
268
+ tokenUsage.completionTokensDetails ??
269
+ {});
270
+ const reasoning = num(cdetails.reasoning_tokens ?? cdetails.reasoningTokens);
271
+ const pdetails = (tokenUsage.prompt_tokens_details ??
272
+ tokenUsage.promptTokensDetails ??
273
+ {});
274
+ const cached = num(pdetails.cached_tokens ?? pdetails.cachedTokens);
275
+ return new Usage({
276
+ inputTokens: inp,
277
+ outputTokens: out,
278
+ cachedTokens: cached,
279
+ reasoningTokens: reasoning,
280
+ });
281
+ }
282
+ return null;
283
+ }
284
+ /**
285
+ * Map LangChain's `usage_metadata` to {@link Usage}. LangChain already reports `input_tokens`
286
+ * *including* the cached read (`cached ⊆ input`, the same convention cendor normalizes to), so no
287
+ * folding is needed. Reasoning is under `output_token_details.reasoning`; cache read/creation under
288
+ * `input_token_details`.
289
+ */
290
+ function usageFromMetadata(meta) {
291
+ return new Usage({
292
+ inputTokens: num(meta.input_tokens),
293
+ outputTokens: num(meta.output_tokens),
294
+ cachedTokens: num(meta.input_token_details?.cache_read),
295
+ reasoningTokens: num(meta.output_token_details?.reasoning),
296
+ cacheWrite: num(meta.input_token_details?.cache_creation),
297
+ });
298
+ }
299
+ /** Read the model id from `llmOutput` or a generation message's `response_metadata`. */
300
+ function modelFromResult(result) {
301
+ const llmOutput = (result.llmOutput ?? {});
302
+ const direct = llmOutput.model_name ?? llmOutput.modelName ?? llmOutput.model;
303
+ if (direct)
304
+ return String(direct);
305
+ for (const gens of result.generations ?? []) {
306
+ for (const gen of gens) {
307
+ const meta = gen.message?.response_metadata ?? {};
308
+ const m = meta.model_name ?? meta.model;
309
+ if (m)
310
+ return String(m);
311
+ }
312
+ }
313
+ return '';
314
+ }
315
+ /** Price the call offline from the bundled snapshot; unknown model ⇒ `cost` stays `null`. */
316
+ function setCost(call, usage) {
317
+ if (usage === null)
318
+ return;
319
+ try {
320
+ call.cost = prices.estimate(call.model, usage.inputTokens, {
321
+ outputTokens: usage.outputTokens,
322
+ cachedTokens: usage.cachedTokens,
323
+ cacheWriteTokens: usage.cacheWrite,
324
+ });
325
+ call.metadata.cost_estimated = true;
326
+ }
327
+ catch (err) {
328
+ if (err instanceof prices.UnknownModelError) {
329
+ call.cost = null;
330
+ }
331
+ else {
332
+ throw err;
333
+ }
334
+ }
335
+ }
336
+ /** LangChain's serialized tool descriptor carries a `name`; default when absent. */
337
+ function serializedName(tool) {
338
+ const name = tool?.name;
339
+ return typeof name === 'string' ? name : undefined;
340
+ }
341
+ /** The message of an error, mirroring Python's `str(exc)`. */
342
+ function errorMessage(err) {
343
+ return err instanceof Error ? err.message : String(err);
344
+ }
345
+ //# sourceMappingURL=langchain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"langchain.js","sourceRoot":"","sources":["../src/langchain.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cendor/core",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "Wrap your LLM client once and capture exact token counts and cost on every call — the shared foundation the other Cendor tools build on.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -10,11 +10,17 @@
10
10
  ".": {
11
11
  "types": "./dist/index.d.ts",
12
12
  "default": "./dist/index.js"
13
+ },
14
+ "./langchain": {
15
+ "types": "./dist/langchain.d.ts",
16
+ "default": "./dist/langchain.js"
13
17
  }
14
18
  },
15
19
  "files": [
16
20
  "dist",
17
- "README.md"
21
+ "README.md",
22
+ "LICENSE",
23
+ "NOTICE"
18
24
  ],
19
25
  "sideEffects": false,
20
26
  "engines": {
@@ -25,9 +31,13 @@
25
31
  "js-tiktoken": "^1.0.15"
26
32
  },
27
33
  "peerDependencies": {
34
+ "@langchain/core": ">=0.3",
28
35
  "@opentelemetry/api": ">=1"
29
36
  },
30
37
  "peerDependenciesMeta": {
38
+ "@langchain/core": {
39
+ "optional": true
40
+ },
31
41
  "@opentelemetry/api": {
32
42
  "optional": true
33
43
  }
@@ -46,7 +56,14 @@
46
56
  "url": "git+https://github.com/cendorhq/cendor-libs-js.git",
47
57
  "directory": "packages/core"
48
58
  },
59
+ "homepage": "https://cendor.ai/docs/core",
60
+ "bugs": {
61
+ "url": "https://github.com/cendorhq/cendor-libs-js/issues"
62
+ },
49
63
  "publishConfig": {
50
64
  "access": "public"
65
+ },
66
+ "devDependencies": {
67
+ "@langchain/core": "^1.2.1"
51
68
  }
52
69
  }