@narumitw/pi-langfuse 0.49.3 → 0.49.4
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 +2 -2
- package/package.json +8 -5
- package/src/runtime.ts +17 -8
- package/src/tracing.ts +14 -6
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ pi -e npm:@narumitw/pi-langfuse
|
|
|
35
35
|
Try a local checkout:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
pi -e ./
|
|
38
|
+
pi -e ./packages/pi-langfuse
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
The Langfuse v4 SDK requires Node.js 20 or newer.
|
|
@@ -173,7 +173,7 @@ The built-in mask specifically protects Langfuse credentials; it is not a genera
|
|
|
173
173
|
## 🗂️ Package layout
|
|
174
174
|
|
|
175
175
|
```txt
|
|
176
|
-
|
|
176
|
+
packages/pi-langfuse/
|
|
177
177
|
├── src/
|
|
178
178
|
│ ├── index.ts # Pi package entrypoint
|
|
179
179
|
│ ├── langfuse.ts # Pi lifecycle integration and slash command
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@narumitw/pi-langfuse",
|
|
3
|
-
"version": "0.49.
|
|
3
|
+
"version": "0.49.4",
|
|
4
4
|
"description": "Pi extension that traces LLM generations and tool activity to Langfuse.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
"./src/index.ts"
|
|
24
24
|
]
|
|
25
25
|
},
|
|
26
|
+
"piExtension": {
|
|
27
|
+
"lifecycle": "stable"
|
|
28
|
+
},
|
|
26
29
|
"scripts": {
|
|
27
30
|
"check": "biome check . && npm run typecheck",
|
|
28
31
|
"format": "biome check --write .",
|
|
@@ -32,9 +35,9 @@
|
|
|
32
35
|
"@earendil-works/pi-coding-agent": "*"
|
|
33
36
|
},
|
|
34
37
|
"devDependencies": {
|
|
35
|
-
"@biomejs/biome": "2.5.
|
|
36
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
37
|
-
"@types/node": "26.
|
|
38
|
+
"@biomejs/biome": "2.5.8",
|
|
39
|
+
"@earendil-works/pi-coding-agent": "0.84.2",
|
|
40
|
+
"@types/node": "26.2.0",
|
|
38
41
|
"typescript": "7.0.2"
|
|
39
42
|
},
|
|
40
43
|
"dependencies": {
|
|
@@ -49,6 +52,6 @@
|
|
|
49
52
|
"repository": {
|
|
50
53
|
"type": "git",
|
|
51
54
|
"url": "https://github.com/narumiruna/pi-extensions",
|
|
52
|
-
"directory": "
|
|
55
|
+
"directory": "packages/pi-langfuse"
|
|
53
56
|
}
|
|
54
57
|
}
|
package/src/runtime.ts
CHANGED
|
@@ -39,7 +39,9 @@ class ProductionObservation implements Observation {
|
|
|
39
39
|
constructor(readonly native: LangfuseObservation) {}
|
|
40
40
|
|
|
41
41
|
update(attributes: ObservationAttributes): Observation {
|
|
42
|
-
|
|
42
|
+
const { sessionId, ...observationAttributes } = attributes;
|
|
43
|
+
this.native.updateOtelSpanAttributes(observationAttributes as LangfuseObservationAttributes);
|
|
44
|
+
applySessionId(this.native, sessionId);
|
|
43
45
|
return this;
|
|
44
46
|
}
|
|
45
47
|
|
|
@@ -51,9 +53,7 @@ class ProductionObservation implements Observation {
|
|
|
51
53
|
if (name !== undefined) {
|
|
52
54
|
this.native.otelSpan.setAttribute(LangfuseOtelSpanAttributes.TRACE_NAME, name);
|
|
53
55
|
}
|
|
54
|
-
|
|
55
|
-
this.native.otelSpan.setAttribute(LangfuseOtelSpanAttributes.TRACE_SESSION_ID, sessionId);
|
|
56
|
-
}
|
|
56
|
+
applySessionId(this.native, sessionId);
|
|
57
57
|
if (tags !== undefined) {
|
|
58
58
|
this.native.otelSpan.setAttribute(LangfuseOtelSpanAttributes.TRACE_TAGS, tags);
|
|
59
59
|
}
|
|
@@ -86,11 +86,14 @@ class ProductionTraceBackend implements TraceBackend {
|
|
|
86
86
|
attributes: ObservationAttributes,
|
|
87
87
|
options: { asType: ObservationType; parent?: Observation },
|
|
88
88
|
): Observation {
|
|
89
|
+
const { sessionId, ...observationAttributes } = attributes;
|
|
89
90
|
const parent = options.parent;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
const native =
|
|
92
|
+
parent instanceof ProductionObservation
|
|
93
|
+
? startChild(parent.native, name, observationAttributes, options.asType)
|
|
94
|
+
: startRoot(name, observationAttributes, options.asType);
|
|
95
|
+
applySessionId(native, sessionId);
|
|
96
|
+
return new ProductionObservation(native);
|
|
94
97
|
}
|
|
95
98
|
|
|
96
99
|
async forceFlush(): Promise<void> {
|
|
@@ -177,6 +180,12 @@ const defaultFactories: RuntimeFactories = {
|
|
|
177
180
|
selectProvider: setLangfuseTracerProvider,
|
|
178
181
|
};
|
|
179
182
|
|
|
183
|
+
function applySessionId(observation: LangfuseObservation, sessionId: string | undefined): void {
|
|
184
|
+
if (sessionId !== undefined) {
|
|
185
|
+
observation.otelSpan.setAttribute(LangfuseOtelSpanAttributes.TRACE_SESSION_ID, sessionId);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
180
189
|
function startRoot(
|
|
181
190
|
name: string,
|
|
182
191
|
attributes: ObservationAttributes,
|
package/src/tracing.ts
CHANGED
|
@@ -234,6 +234,14 @@ export class TraceRecorder {
|
|
|
234
234
|
private readonly context: RecorderContext,
|
|
235
235
|
) {}
|
|
236
236
|
|
|
237
|
+
private startObservation(
|
|
238
|
+
name: string,
|
|
239
|
+
attributes: ObservationAttributes,
|
|
240
|
+
options: { asType: ObservationType; parent?: Observation },
|
|
241
|
+
): Observation {
|
|
242
|
+
return this.backend.start(name, { ...attributes, sessionId: this.context.sessionId }, options);
|
|
243
|
+
}
|
|
244
|
+
|
|
237
245
|
hasActiveTrace(): boolean {
|
|
238
246
|
return this.root !== undefined;
|
|
239
247
|
}
|
|
@@ -275,7 +283,7 @@ export class TraceRecorder {
|
|
|
275
283
|
? "git:detached"
|
|
276
284
|
: undefined;
|
|
277
285
|
|
|
278
|
-
this.root = this.
|
|
286
|
+
this.root = this.startObservation("pi.agent", attributes, { asType: "agent" });
|
|
279
287
|
this.root.updateTrace?.({
|
|
280
288
|
name: "pi.trace",
|
|
281
289
|
sessionId: this.context.sessionId,
|
|
@@ -296,7 +304,7 @@ export class TraceRecorder {
|
|
|
296
304
|
this.lastAssistant = undefined;
|
|
297
305
|
this.unresolvedToolErrors = 0;
|
|
298
306
|
this.attemptIndex = index;
|
|
299
|
-
this.attempt = this.
|
|
307
|
+
this.attempt = this.startObservation(
|
|
300
308
|
"pi.attempt",
|
|
301
309
|
{
|
|
302
310
|
metadata: {
|
|
@@ -325,7 +333,7 @@ export class TraceRecorder {
|
|
|
325
333
|
if (this.turn) this.closeTurn("Interrupted by the next Pi turn.", "ERROR");
|
|
326
334
|
this.counters.turns += 1;
|
|
327
335
|
this.turnIndex = turnIndex;
|
|
328
|
-
this.turn = this.
|
|
336
|
+
this.turn = this.startObservation(
|
|
329
337
|
"pi.turn",
|
|
330
338
|
{ metadata: { "pi.turn.index": turnIndex }, version: TRACE_SCHEMA_VERSION },
|
|
331
339
|
{ asType: "span", parent: this.attempt ?? this.root },
|
|
@@ -372,7 +380,7 @@ export class TraceRecorder {
|
|
|
372
380
|
...(input.model?.api ? { "pi.request.api": input.model.api } : {}),
|
|
373
381
|
...(input.thinkingLevel ? { "pi.request.thinking_level": input.thinkingLevel } : {}),
|
|
374
382
|
};
|
|
375
|
-
const observation = this.
|
|
383
|
+
const observation = this.startObservation(
|
|
376
384
|
"pi.llm",
|
|
377
385
|
{
|
|
378
386
|
...(input.payload !== undefined ? { input: this.capture(input.payload) } : {}),
|
|
@@ -559,7 +567,7 @@ export class TraceRecorder {
|
|
|
559
567
|
this.closeCompaction("Interrupted by another Pi compaction.");
|
|
560
568
|
this.counters.compactions += 1;
|
|
561
569
|
this.compaction = {
|
|
562
|
-
observation: this.
|
|
570
|
+
observation: this.startObservation(
|
|
563
571
|
"pi.compaction",
|
|
564
572
|
{
|
|
565
573
|
metadata: {
|
|
@@ -711,7 +719,7 @@ export class TraceRecorder {
|
|
|
711
719
|
}
|
|
712
720
|
|
|
713
721
|
private startToolObservation(toolCallId: string, toolName: string, args?: unknown): Observation {
|
|
714
|
-
return this.
|
|
722
|
+
return this.startObservation(
|
|
715
723
|
`pi.tool.${toolName}`,
|
|
716
724
|
{
|
|
717
725
|
...(args !== undefined ? { input: this.capture(args) } : {}),
|