@cat-factory/observability-langfuse 0.10.106 → 0.11.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.
- package/README.md +17 -8
- package/dist/index.d.ts +13 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +50 -179
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -8,14 +8,23 @@ when wired into a facade every LLM call: container-agent calls (through the LLM
|
|
|
8
8
|
agent): surfaces in Langfuse as a generation grouped under its run's trace, plus
|
|
9
9
|
optional container tool spans.
|
|
10
10
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
The sink
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
## What it is: the OTLP exporter, pointed at Langfuse
|
|
12
|
+
|
|
13
|
+
The sink is `@cat-factory/observability-otel`'s fetch-based OTLP/HTTP exporter with three
|
|
14
|
+
Langfuse-specific decisions in its constructor: the endpoint `{baseUrl}/api/public/otel`
|
|
15
|
+
(onto which the exporter appends `/v1/traces`), HTTP Basic auth over the key pair, and the
|
|
16
|
+
`x-langfuse-ingestion-version: 4` header that v4 needs for real-time ingestion. Metrics
|
|
17
|
+
are off, because Langfuse implements the traces signal only.
|
|
18
|
+
|
|
19
|
+
It used to be its own client speaking Langfuse's batch **ingestion API**
|
|
20
|
+
(`POST /api/public/ingestion`). That API is deprecated, sunsets on Langfuse Cloud on
|
|
21
|
+
**2026-11-16**, and the `trace-create` / `generation-create` / `span-create` events it sent
|
|
22
|
+
are already unsupported on the v4 data model. OTLP is the supported path and this repo
|
|
23
|
+
already spoke it.
|
|
24
|
+
|
|
25
|
+
Neither package depends on the official `langfuse` Node SDK or on any `@opentelemetry/*`
|
|
26
|
+
package: those rely on Node-only APIs unavailable on the Cloudflare Worker runtime
|
|
27
|
+
(workerd), which is what keeps the sink byte-for-byte identical on both facades.
|
|
19
28
|
|
|
20
29
|
## Behaviour
|
|
21
30
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Logger } from '@cat-factory/kernel';
|
|
2
|
+
import { OtelTraceSink } from '@cat-factory/observability-otel';
|
|
2
3
|
export interface LangfuseSinkConfig {
|
|
3
4
|
/** Langfuse public key (`pk-lf-…`). */
|
|
4
5
|
publicKey: string;
|
|
@@ -6,20 +7,23 @@ export interface LangfuseSinkConfig {
|
|
|
6
7
|
secretKey: string;
|
|
7
8
|
/** Host of the Langfuse instance. Default: Langfuse Cloud (`https://cloud.langfuse.com`). */
|
|
8
9
|
baseUrl?: string;
|
|
10
|
+
/** OTLP resource `service.name`, as it appears on the exported spans. */
|
|
11
|
+
serviceName?: string;
|
|
9
12
|
/** Optional logger for swallowed errors. */
|
|
10
13
|
logger?: Logger;
|
|
11
14
|
/** Injectable fetch (tests); defaults to the global `fetch`. */
|
|
12
15
|
fetchImpl?: typeof fetch;
|
|
13
16
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
/**
|
|
18
|
+
* The OTLP exporter, configured for a Langfuse project.
|
|
19
|
+
*
|
|
20
|
+
* A subclass rather than a factory returning the base type, because a facade composing several
|
|
21
|
+
* sinks has to be able to say WHICH destination it wired: `CompositeTraceSink` holds a list, and
|
|
22
|
+
* two members of the same class are indistinguishable to the wiring assertions that keep the
|
|
23
|
+
* facades symmetric.
|
|
24
|
+
*/
|
|
25
|
+
export declare class LangfuseTraceSink extends OtelTraceSink {
|
|
19
26
|
constructor(config: LangfuseSinkConfig);
|
|
20
|
-
recordGeneration(event: LlmGenerationEvent): Promise<void>;
|
|
21
|
-
recordToolSpans(context: LlmToolSpanContext, spans: LlmToolSpan[]): Promise<void>;
|
|
22
|
-
private send;
|
|
23
27
|
}
|
|
24
28
|
/** Build a {@link LangfuseTraceSink}. Returns the opt-in sink wired into a facade. */
|
|
25
29
|
export declare function createLangfuseSink(config: LangfuseSinkConfig): LangfuseTraceSink;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAA;AAuC/D,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAA;IACjB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAA;IACjB,6FAA6F;IAC7F,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACzB;AAMD;;;;;;;GAOG;AACH,qBAAa,iBAAkB,SAAQ,aAAa;IAClD,YAAY,MAAM,EAAE,kBAAkB,EAarC;CACF;AAED,sFAAsF;AACtF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,iBAAiB,CAEhF"}
|
package/dist/index.js
CHANGED
|
@@ -1,192 +1,63 @@
|
|
|
1
|
-
import {
|
|
2
|
-
//
|
|
3
|
-
// (`POST /api/public/ingestion`, HTTP Basic auth = public:secret key, batched JSON
|
|
4
|
-
// events) using only the global `fetch`/`crypto`/`btoa` — NO `langfuse` Node SDK and
|
|
5
|
-
// NO `@opentelemetry/*`, both of which depend on Node-only APIs that are unavailable on
|
|
6
|
-
// the Cloudflare Worker runtime (workerd). This keeps the sink byte-for-byte identical
|
|
7
|
-
// across the Worker and Node facades, which is the whole reason it exists as its own
|
|
8
|
-
// package: see `LlmTraceSink` in `@cat-factory/kernel`.
|
|
1
|
+
import { OtelTraceSink } from '@cat-factory/observability-otel';
|
|
2
|
+
// The opt-in Langfuse trace sink, which is now the OTLP exporter pointed at Langfuse.
|
|
9
3
|
//
|
|
10
|
-
//
|
|
11
|
-
// (
|
|
12
|
-
//
|
|
4
|
+
// It used to be its own fetch client speaking Langfuse's ingestion API
|
|
5
|
+
// (`POST /api/public/ingestion`, batched `trace-create` / `generation-create` / `span-create`
|
|
6
|
+
// events). That API is deprecated and sunsets on Langfuse Cloud on 2026-11-16, and the three event
|
|
7
|
+
// types this sent are already unsupported on the v4 data model: "Trace, span, and generation events
|
|
8
|
+
// via the legacy batch ingestion API are not supported on the v4 data model". The supported path is
|
|
9
|
+
// OTLP, which this repo already speaks: `@cat-factory/observability-otel` hand-writes an OTLP/HTTP
|
|
10
|
+
// JSON exporter for exactly the same three shapes, so the migration retargets an encoder rather
|
|
11
|
+
// than writing one, and Langfuse becomes a DESTINATION instead of a second recording path.
|
|
13
12
|
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
13
|
+
// What differs from a plain collector, and it is only these three things:
|
|
14
|
+
// - the endpoint is `{base}/api/public/otel`, so the exporter's own `/v1/traces` append lands on
|
|
15
|
+
// Langfuse's documented signal path;
|
|
16
|
+
// - auth is HTTP Basic over `publicKey:secretKey`, the same credential pair as before;
|
|
17
|
+
// - `x-langfuse-ingestion-version: 4` is required for real-time ingestion on v4. Without it the
|
|
18
|
+
// data still arrives, up to ten minutes late, which is the kind of delay that reads as data
|
|
19
|
+
// loss to whoever is watching a run.
|
|
20
20
|
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
// - The costs that DO exist are telemetry-side, not run-side: +1 detached subrequest
|
|
34
|
-
// per proxy invocation (~2 of the Worker's 1000-subrequest budget), negligible
|
|
35
|
-
// `waitUntil` CPU (I/O-bound, timeout-capped), and N calls ⇒ N POSTs — a very chatty
|
|
36
|
-
// run could brush Langfuse ingestion rate limits and drop some batches, degrading
|
|
37
|
-
// telemetry COMPLETENESS only, never the run. (Tool spans are batched per poll, so
|
|
38
|
-
// they don't multiply.)
|
|
21
|
+
// METRICS ARE OFF because Langfuse implements the traces signal only. Posting `/v1/metrics` there
|
|
22
|
+
// would 404 once per generation, a per-call failure that says nothing about the deployment.
|
|
23
|
+
//
|
|
24
|
+
// The contract the two sinks share is unchanged and is documented on the exporter: observability
|
|
25
|
+
// must never break the product, so every method swallows its own errors (logging at most a
|
|
26
|
+
// warning), each POST is timeout-bounded, and a dropped batch is the worst case. No `langfuse` SDK
|
|
27
|
+
// and no `@opentelemetry/*`: both depend on Node-only APIs that are unavailable on workerd, which
|
|
28
|
+
// is why the fetch-based exporter exists at all.
|
|
29
|
+
//
|
|
30
|
+
// Read 2026-08-18: https://langfuse.com/docs/api, https://langfuse.com/docs/compatibility,
|
|
31
|
+
// https://langfuse.com/integrations/native/opentelemetry
|
|
32
|
+
/** Langfuse Cloud EU. The US, Japan and HIPAA clouds are the same shape on their own hosts. */
|
|
39
33
|
const DEFAULT_BASE_URL = 'https://cloud.langfuse.com';
|
|
40
|
-
/**
|
|
41
|
-
|
|
42
|
-
* path: the proxied feeder records under the platform's `waitUntil` budget and the
|
|
43
|
-
* inline feeder dispatches without awaiting, so a hung Langfuse endpoint must abort
|
|
44
|
-
* rather than dangle. A dropped batch is the documented best-effort worst case.
|
|
45
|
-
*/
|
|
46
|
-
const SEND_TIMEOUT_MS = 10_000;
|
|
47
|
-
function iso(ms) {
|
|
48
|
-
return new Date(ms).toISOString();
|
|
49
|
-
}
|
|
34
|
+
/** Langfuse's OTLP path, onto which the exporter appends the `/v1/traces` signal segment. */
|
|
35
|
+
const OTEL_PATH = '/api/public/otel';
|
|
50
36
|
function basicAuth(publicKey, secretKey) {
|
|
51
37
|
return `Basic ${btoa(`${publicKey}:${secretKey}`)}`;
|
|
52
38
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
39
|
+
/**
|
|
40
|
+
* The OTLP exporter, configured for a Langfuse project.
|
|
41
|
+
*
|
|
42
|
+
* A subclass rather than a factory returning the base type, because a facade composing several
|
|
43
|
+
* sinks has to be able to say WHICH destination it wired: `CompositeTraceSink` holds a list, and
|
|
44
|
+
* two members of the same class are indistinguishable to the wiring assertions that keep the
|
|
45
|
+
* facades symmetric.
|
|
46
|
+
*/
|
|
47
|
+
export class LangfuseTraceSink extends OtelTraceSink {
|
|
58
48
|
constructor(config) {
|
|
59
49
|
const base = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, '');
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// Group every call of a run under one trace (keyed by the execution id); inline
|
|
67
|
-
// single-shot calls (no execution) become their own standalone trace.
|
|
68
|
-
const traceId = event.executionId ?? crypto.randomUUID();
|
|
69
|
-
const generation = {
|
|
70
|
-
id: crypto.randomUUID(),
|
|
71
|
-
traceId,
|
|
72
|
-
name: event.agentKind,
|
|
73
|
-
startTime: iso(event.startedAt),
|
|
74
|
-
endTime: iso(event.endedAt),
|
|
75
|
-
model: event.model,
|
|
76
|
-
usage: {
|
|
77
|
-
// Langfuse's `input` is the whole input side, so the three orthogonal classes are
|
|
78
|
-
// summed back for it; the split rides the metadata below, where a cache-read-dominated
|
|
79
|
-
// generation is still distinguishable from a fresh one.
|
|
80
|
-
input: event.promptTokens + event.cacheReadTokens + event.cacheWriteTokens,
|
|
81
|
-
output: event.completionTokens,
|
|
82
|
-
total: event.totalTokens,
|
|
83
|
-
unit: 'TOKENS',
|
|
84
|
-
},
|
|
85
|
-
level: event.ok ? 'DEFAULT' : 'ERROR',
|
|
86
|
-
metadata: {
|
|
87
|
-
provider: event.provider,
|
|
88
|
-
agentKind: event.agentKind,
|
|
89
|
-
finishReason: event.finishReason,
|
|
90
|
-
freshInputTokens: event.promptTokens,
|
|
91
|
-
cacheReadTokens: event.cacheReadTokens,
|
|
92
|
-
cacheWriteTokens: event.cacheWriteTokens,
|
|
93
|
-
workspaceId: event.workspaceId,
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
// Prompt/response bodies are present only when prompt recording is on (the same
|
|
97
|
-
// `LLM_RECORD_PROMPTS` switch the local store honours): omit empty bodies entirely.
|
|
98
|
-
if (event.input)
|
|
99
|
-
generation.input = event.input;
|
|
100
|
-
if (event.output)
|
|
101
|
-
generation.output = event.output;
|
|
102
|
-
if (event.errorMessage)
|
|
103
|
-
generation.statusMessage = event.errorMessage;
|
|
104
|
-
await this.send([
|
|
105
|
-
{
|
|
106
|
-
id: crypto.randomUUID(),
|
|
107
|
-
type: 'trace-create',
|
|
108
|
-
timestamp: iso(event.endedAt),
|
|
109
|
-
body: {
|
|
110
|
-
id: traceId,
|
|
111
|
-
// A run trace is upserted by every call it groups, so keep the trace body
|
|
112
|
-
// stable across them: the per-call agent kind lives on each generation
|
|
113
|
-
// (its `name` + metadata), NOT as a trace tag that the next call would clobber.
|
|
114
|
-
name: event.executionId ? `run ${event.executionId}` : event.agentKind,
|
|
115
|
-
metadata: { workspaceId: event.workspaceId },
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
id: crypto.randomUUID(),
|
|
120
|
-
type: 'generation-create',
|
|
121
|
-
timestamp: iso(event.endedAt),
|
|
122
|
-
body: generation,
|
|
50
|
+
super({
|
|
51
|
+
endpoint: `${base}${OTEL_PATH}`,
|
|
52
|
+
exportMetrics: false,
|
|
53
|
+
headers: {
|
|
54
|
+
authorization: basicAuth(config.publicKey, config.secretKey),
|
|
55
|
+
'x-langfuse-ingestion-version': '4',
|
|
123
56
|
},
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (!context.executionId || spans.length === 0)
|
|
129
|
-
return;
|
|
130
|
-
const traceId = context.executionId;
|
|
131
|
-
const batch = spans.map((span) => ({
|
|
132
|
-
id: crypto.randomUUID(),
|
|
133
|
-
type: 'span-create',
|
|
134
|
-
timestamp: iso(span.endedAt),
|
|
135
|
-
body: {
|
|
136
|
-
id: crypto.randomUUID(),
|
|
137
|
-
traceId,
|
|
138
|
-
name: span.tool,
|
|
139
|
-
startTime: iso(span.startedAt),
|
|
140
|
-
endTime: iso(span.endedAt),
|
|
141
|
-
level: span.ok ? 'DEFAULT' : 'ERROR',
|
|
142
|
-
// The call's arguments and result go in Langfuse's own input/output slots rather than
|
|
143
|
-
// metadata, so the trajectory reads in the UI the way a generation's prompt does.
|
|
144
|
-
// Present only when the double gate allowed capture (upstream blanks them otherwise).
|
|
145
|
-
...(span.args ? { input: span.args } : {}),
|
|
146
|
-
...(span.result ? { output: span.result } : {}),
|
|
147
|
-
metadata: {
|
|
148
|
-
agentKind: context.agentKind,
|
|
149
|
-
// The ordinal a trajectory orders by: a tool loop routinely fires several calls inside
|
|
150
|
-
// one millisecond, so start time alone cannot sequence them. The dispatch rides with
|
|
151
|
-
// it because `seq` restarts at zero on each one, so a re-run's spans would otherwise
|
|
152
|
-
// be indistinguishable from the first round's.
|
|
153
|
-
...(context.jobId ? { jobId: context.jobId } : {}),
|
|
154
|
-
...(span.seq !== undefined ? { seq: span.seq } : {}),
|
|
155
|
-
...(span.argsDropped ? { argsDroppedChars: span.argsDropped } : {}),
|
|
156
|
-
...(span.resultDropped ? { resultDroppedChars: span.resultDropped } : {}),
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
}));
|
|
160
|
-
await this.send(batch);
|
|
161
|
-
}
|
|
162
|
-
async send(batch) {
|
|
163
|
-
try {
|
|
164
|
-
const res = await this.fetchImpl(this.endpoint, {
|
|
165
|
-
method: 'POST',
|
|
166
|
-
headers: {
|
|
167
|
-
'content-type': 'application/json',
|
|
168
|
-
authorization: this.authorization,
|
|
169
|
-
},
|
|
170
|
-
body: JSON.stringify({ batch }),
|
|
171
|
-
// Bound the request so a hung endpoint can't tie up the caller's waitUntil
|
|
172
|
-
// budget; an abort lands in the catch below and drops the batch (best-effort).
|
|
173
|
-
signal: AbortSignal.timeout(SEND_TIMEOUT_MS),
|
|
174
|
-
});
|
|
175
|
-
// 207 = partial success (per-event errors in the body); anything else non-2xx is
|
|
176
|
-
// a hard failure. Either way we only log — observability never breaks the caller.
|
|
177
|
-
if (!res.ok && res.status !== 207) {
|
|
178
|
-
this.logger?.warn('langfuse: ingestion rejected batch', {
|
|
179
|
-
scope: 'langfuse',
|
|
180
|
-
status: res.status,
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
catch (err) {
|
|
185
|
-
this.logger?.warn('langfuse: failed to post ingestion batch', {
|
|
186
|
-
scope: 'langfuse',
|
|
187
|
-
err: getErrorMessage(err),
|
|
188
|
-
});
|
|
189
|
-
}
|
|
57
|
+
...(config.serviceName ? { serviceName: config.serviceName } : {}),
|
|
58
|
+
...(config.logger ? { logger: config.logger } : {}),
|
|
59
|
+
...(config.fetchImpl ? { fetchImpl: config.fetchImpl } : {}),
|
|
60
|
+
});
|
|
190
61
|
}
|
|
191
62
|
}
|
|
192
63
|
/** Build a {@link LangfuseTraceSink}. Returns the opt-in sink wired into a facade. */
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAA;AAE/D,sFAAsF;AACtF,EAAE;AACF,uEAAuE;AACvE,8FAA8F;AAC9F,mGAAmG;AACnG,oGAAoG;AACpG,oGAAoG;AACpG,mGAAmG;AACnG,gGAAgG;AAChG,2FAA2F;AAC3F,EAAE;AACF,0EAA0E;AAC1E,mGAAmG;AACnG,yCAAyC;AACzC,yFAAyF;AACzF,kGAAkG;AAClG,gGAAgG;AAChG,yCAAyC;AACzC,EAAE;AACF,kGAAkG;AAClG,4FAA4F;AAC5F,EAAE;AACF,iGAAiG;AACjG,2FAA2F;AAC3F,mGAAmG;AACnG,kGAAkG;AAClG,iDAAiD;AACjD,EAAE;AACF,2FAA2F;AAC3F,yDAAyD;AAEzD,+FAA+F;AAC/F,MAAM,gBAAgB,GAAG,4BAA4B,CAAA;AAErD,6FAA6F;AAC7F,MAAM,SAAS,GAAG,kBAAkB,CAAA;AAiBpC,SAAS,SAAS,CAAC,SAAiB,EAAE,SAAiB;IACrD,OAAO,SAAS,IAAI,CAAC,GAAG,SAAS,IAAI,SAAS,EAAE,CAAC,EAAE,CAAA;AACrD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,iBAAkB,SAAQ,aAAa;IAClD,YAAY,MAA0B;QACpC,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,gBAAgB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QACrE,KAAK,CAAC;YACJ,QAAQ,EAAE,GAAG,IAAI,GAAG,SAAS,EAAE;YAC/B,aAAa,EAAE,KAAK;YACpB,OAAO,EAAE;gBACP,aAAa,EAAE,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC;gBAC5D,8BAA8B,EAAE,GAAG;aACpC;YACD,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClE,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7D,CAAC,CAAA;IACJ,CAAC;CACF;AAED,sFAAsF;AACtF,MAAM,UAAU,kBAAkB,CAAC,MAA0B;IAC3D,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAA;AACtC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/observability-langfuse",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Opt-in Langfuse trace sink for the Agent Architecture Board.
|
|
3
|
+
"version": "0.11.0",
|
|
4
|
+
"description": "Opt-in Langfuse trace sink for the Agent Architecture Board. The workerd-safe OTLP/HTTP exporter pointed at Langfuse's OpenTelemetry endpoint, so LLM generations and container tool spans stream unchanged on both the Cloudflare Worker and Node facades.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/kibertoad/cat-factory.git",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"access": "public"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@cat-factory/kernel": "0.
|
|
27
|
+
"@cat-factory/kernel": "0.313.0",
|
|
28
|
+
"@cat-factory/observability-otel": "0.22.0"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
31
|
"typescript": "7.0.2",
|