pi-langfuse 1.0.0 → 1.1.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 +270 -59
- package/README_CN.md +273 -61
- package/image.png +0 -0
- package/index.ts +877 -325
- package/package.json +18 -3
package/README.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# pi-langfuse
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/pi-langfuse)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
[**English**](./README.md) | [**简体中文**](./README_CN.md)
|
|
7
|
+
|
|
8
|
+
Langfuse observability extension for [Pi Coding Agent](https://github.com/earendil-works/pi-coding-agent). Sends complete Pi agent runs to [Langfuse](https://langfuse.com) so you can inspect the user prompt, root agent workflow, every LLM generation, every tool call, final assistant response, usage, cost, and health scores in one trace.
|
|
4
9
|
|
|
5
10
|
## Why Langfuse?
|
|
6
11
|
|
|
@@ -8,113 +13,319 @@ Langfuse provides open-source observability for LLM applications. This extension
|
|
|
8
13
|
|
|
9
14
|
## Features
|
|
10
15
|
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
16
|
+
- **Complete Agent Traces**: Creates one trace per user prompt with a root `agent` observation containing the prompt input and final assistant output.
|
|
17
|
+
- **Per-Request Generations**: Records a separate `generation` observation for every provider request, including the actual provider payload instead of only the original prompt.
|
|
18
|
+
- **Final Message Capture**: Uses finalized assistant messages for generation and root outputs, so Langfuse shows what the user actually saw in Pi.
|
|
19
|
+
- **Tool Observability**: Creates Langfuse `tool` observations for every tool call, including arguments, results, and error states.
|
|
20
|
+
- **Parallel Tool Safety**: Correlates tool observations by `toolCallId`, avoiding result mix-ups when Pi runs tools concurrently.
|
|
21
|
+
- **Session Correlation**: Groups traces from the same Pi session under a shared Langfuse session ID.
|
|
22
|
+
- **Cost and Token Tracking**: Records usage and cost details on each generation when Pi/provider payloads expose them.
|
|
23
|
+
- **Evaluation Scores**: Automatically computes and sends tool success rates, error counts, and session health metrics.
|
|
24
|
+
- **Defensive Payload Shaping**: Parses JSON-like strings when possible, limits object depth, and truncates large payloads before upload.
|
|
25
|
+
|
|
26
|
+
## Highlights
|
|
27
|
+
|
|
28
|
+
`pi-langfuse` is designed to make a Pi run readable as an agent workflow, not just a bag of logs:
|
|
29
|
+
|
|
30
|
+
- The trace input/output mirrors the root `agent` observation, making the run understandable from the Langfuse trace list and detail view.
|
|
31
|
+
- The first generation in a tool-using run can show the assistant's tool-call message, the tool observation shows execution I/O, and the follow-up generation shows the final natural-language answer.
|
|
32
|
+
- Tool failures are marked on the tool observation and reflected in trace-level scores, while later generations still preserve the tool error result in their input history.
|
|
33
|
+
- Shutdown and interrupted runs flush pending telemetry and mark unfinished observations as cancelled/warning instead of silently losing the trace.
|
|
17
34
|
|
|
18
|
-
##
|
|
35
|
+
## Prerequisites
|
|
36
|
+
|
|
37
|
+
- **Node.js** >= 22
|
|
38
|
+
- **Pi Coding Agent** installed and configured
|
|
39
|
+
- A **Langfuse** account ([cloud](https://cloud.langfuse.com) or self-hosted)
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
### Option 1: Install via npm (recommended for users)
|
|
19
44
|
|
|
20
|
-
### Via npm (recommended)
|
|
21
45
|
```bash
|
|
22
46
|
pi install npm:pi-langfuse
|
|
23
47
|
```
|
|
24
48
|
|
|
49
|
+
Pi will download the package and register it as an extension.
|
|
50
|
+
|
|
51
|
+
### Option 2: Install from local source (recommended for development)
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone <your-repo-url>
|
|
55
|
+
cd pi-langfuse
|
|
56
|
+
npm install
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Then tell Pi to use it:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pi link /path/to/pi-langfuse
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Or run Pi from the project directory — Pi auto-discovers extensions in the current directory's `package.json`.
|
|
66
|
+
|
|
25
67
|
## Configuration
|
|
26
68
|
|
|
27
|
-
|
|
69
|
+
You need Langfuse API keys. Get them from **Langfuse Cloud** → **Settings** → **API Keys**.
|
|
28
70
|
|
|
29
|
-
|
|
71
|
+
There are three ways to configure the extension:
|
|
30
72
|
|
|
31
|
-
|
|
32
|
-
- `LANGFUSE_SECRET_KEY`
|
|
33
|
-
- `LANGFUSE_HOST` (optional, defaults to `https://cloud.langfuse.com`)
|
|
73
|
+
### Method 1: Interactive setup (easiest)
|
|
34
74
|
|
|
35
|
-
|
|
75
|
+
Run any `pi` command with the extension loaded. On first run without configuration, Pi will prompt you in the CLI or TUI for:
|
|
36
76
|
|
|
37
|
-
|
|
77
|
+
1. **Langfuse public key** — starts with `pk-lf-...`
|
|
78
|
+
2. **Langfuse secret key** — starts with `sk-lf-...`
|
|
79
|
+
3. **Langfuse host** — defaults to `https://cloud.langfuse.com`
|
|
38
80
|
|
|
39
|
-
|
|
81
|
+
The extension saves these to a local `config.json` (ignored by git).
|
|
40
82
|
|
|
41
|
-
|
|
83
|
+
To re-run setup at any time:
|
|
84
|
+
|
|
85
|
+
```
|
|
42
86
|
/langfuse-setup
|
|
43
87
|
```
|
|
44
88
|
|
|
89
|
+
### Method 2: Environment variables
|
|
90
|
+
|
|
91
|
+
Set these before starting Pi:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
export LANGFUSE_PUBLIC_KEY="pk-lf-xxxx"
|
|
95
|
+
export LANGFUSE_SECRET_KEY="sk-lf-xxxx"
|
|
96
|
+
export LANGFUSE_BASE_URL="https://cloud.langfuse.com" # optional; LANGFUSE_HOST is also supported
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The extension checks the local `config.json` first, then falls back to environment variables.
|
|
100
|
+
|
|
101
|
+
### Method 3: Local config.json (development only)
|
|
102
|
+
|
|
103
|
+
For local development, create a `config.json` in the project root:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"publicKey": "pk-lf-xxxx",
|
|
108
|
+
"secretKey": "sk-lf-xxxx",
|
|
109
|
+
"host": "https://cloud.langfuse.com"
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
> **⚠️ Security**: `config.json` is not tracked by git. Never commit API keys to version control.
|
|
114
|
+
|
|
45
115
|
## Usage
|
|
46
116
|
|
|
47
|
-
###
|
|
117
|
+
### Basic usage
|
|
118
|
+
|
|
119
|
+
Run Pi as usual — the extension auto-loads and traces every agent run:
|
|
48
120
|
|
|
49
121
|
```bash
|
|
50
|
-
pi "
|
|
122
|
+
pi "Explain the architecture of Redis"
|
|
51
123
|
```
|
|
52
124
|
|
|
53
|
-
|
|
125
|
+
After the session ends, check your [Langfuse dashboard](https://cloud.langfuse.com) for the trace.
|
|
126
|
+
|
|
127
|
+
### Verify the extension is loaded
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
pi list
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
You should see `pi-langfuse` in the list of installed packages.
|
|
134
|
+
|
|
135
|
+
### Multiple sessions
|
|
136
|
+
|
|
137
|
+
Each Pi session gets its own Langfuse session ID. Each user prompt within that Pi session becomes a separate Langfuse trace grouped under the same session.
|
|
138
|
+
|
|
139
|
+
## Development Setup
|
|
140
|
+
|
|
141
|
+
If you're contributing to this extension:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Clone and install dependencies
|
|
145
|
+
git clone <your-repo-url>
|
|
146
|
+
cd pi-langfuse
|
|
147
|
+
npm install
|
|
148
|
+
|
|
149
|
+
# Type-check your changes
|
|
150
|
+
npm run typecheck
|
|
151
|
+
|
|
152
|
+
# Test with Pi
|
|
153
|
+
pi "test prompt"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Project structure
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
pi-langfuse/
|
|
160
|
+
├── index.ts # Extension entrypoint and core logic
|
|
161
|
+
├── package.json # Package metadata
|
|
162
|
+
├── tsconfig.json # TypeScript configuration
|
|
163
|
+
├── config.json # Local credentials (git-ignored)
|
|
164
|
+
├── types/
|
|
165
|
+
│ ├── pi-coding-agent.d.ts # Pi extension API types
|
|
166
|
+
│ └── node-shims.d.ts # Node.js module shims
|
|
167
|
+
├── .agents/
|
|
168
|
+
│ └── skills/
|
|
169
|
+
│ └── langfuse/
|
|
170
|
+
│ └── SKILL.md # Langfuse CLI skill for data queries
|
|
171
|
+
├── AGENTS.md # Developer guide (extended)
|
|
172
|
+
├── README.md # This file
|
|
173
|
+
├── README_CN.md # Chinese translation
|
|
174
|
+
└── AGENTS_CN.md # Developer guide (Chinese)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Validation
|
|
178
|
+
|
|
179
|
+
There is no dedicated test suite yet. To validate changes:
|
|
180
|
+
|
|
181
|
+
1. Run `npm run typecheck` for TypeScript errors
|
|
182
|
+
2. Start Pi with the extension enabled
|
|
183
|
+
3. Run a few prompts
|
|
184
|
+
4. Confirm traces, the root agent observation, tool observations, generations, and evaluation scores appear in your Langfuse project
|
|
54
185
|
|
|
55
186
|
## Trace Model
|
|
56
187
|
|
|
57
188
|
```
|
|
58
189
|
Trace (name: "pi-agent")
|
|
59
190
|
├── Session ID: <pi-session-id>
|
|
60
|
-
├──
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
├──
|
|
66
|
-
├──
|
|
67
|
-
|
|
191
|
+
├── input: user prompt, images/context summary when present
|
|
192
|
+
├── output: final assistant response
|
|
193
|
+
└── Agent observation (name: "pi-agent", type: agent)
|
|
194
|
+
├── input: current user prompt
|
|
195
|
+
├── output: final assistant response
|
|
196
|
+
├── Generation observation (name: "llm-generation", type: generation)
|
|
197
|
+
│ ├── input: provider request payload / message history
|
|
198
|
+
│ ├── output: finalized assistant message or tool-call message
|
|
199
|
+
│ ├── model, usageDetails, costDetails
|
|
200
|
+
│ └── metadata: provider/request details
|
|
201
|
+
└── Tool observation (name: "<tool-name>", type: tool)
|
|
202
|
+
├── input: tool parameters
|
|
203
|
+
├── output: tool result
|
|
204
|
+
└── metadata: toolCallId, isError
|
|
68
205
|
```
|
|
69
206
|
|
|
70
207
|
## What Gets Tracked
|
|
71
208
|
|
|
72
209
|
### Trace Level
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
210
|
+
| Field | Description |
|
|
211
|
+
|-------|-------------|
|
|
212
|
+
| `input` | User prompt, with images/context summary when available |
|
|
213
|
+
| `output` | Final assistant response shown in Pi |
|
|
214
|
+
| `sessionId` | Pi session identifier |
|
|
215
|
+
| `metadata.model` | Model identifier (e.g., "MiniMax-M2.7") |
|
|
216
|
+
| `metadata.provider` | LLM provider name |
|
|
217
|
+
| `metadata.cwd` | Working directory |
|
|
218
|
+
|
|
219
|
+
### Agent Observation (Root Workflow)
|
|
220
|
+
| Field | Description |
|
|
221
|
+
|-------|-------------|
|
|
222
|
+
| `type` | `agent` |
|
|
223
|
+
| `name` | `pi-agent` |
|
|
224
|
+
| `input` | Current user prompt payload |
|
|
225
|
+
| `output` | Final assistant response |
|
|
226
|
+
| `metadata.sessionId` | Pi session identifier |
|
|
227
|
+
| `metadata.cwd` | Working directory |
|
|
228
|
+
| `metadata.model` | Selected model when available |
|
|
229
|
+
| `metadata.provider` | Provider when available |
|
|
230
|
+
|
|
231
|
+
### Evaluation Scores (Trace Level)
|
|
232
|
+
|
|
233
|
+
| Score Name | Type | Description |
|
|
234
|
+
|------------|------|-------------|
|
|
235
|
+
| `tool_call_count` | number | Total tool calls in session |
|
|
236
|
+
| `turn_count` | number | Number of assistant turns |
|
|
237
|
+
| `total_tool_errors` | number | Tools that returned errors |
|
|
238
|
+
| `tool_success_rate` | float (0-1) | Ratio of successful tool calls |
|
|
239
|
+
| `session_had_errors` | 0 or 1 | Whether any tool errored |
|
|
77
240
|
|
|
78
241
|
### Generation Observations (LLM Calls)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
242
|
+
| Field | Description |
|
|
243
|
+
|-------|-------------|
|
|
244
|
+
| `type` | `generation` |
|
|
245
|
+
| `name` | `llm-generation` |
|
|
246
|
+
| `input` | Actual provider request payload / message history |
|
|
247
|
+
| `output` | Finalized assistant message, including tool-call payloads for tool-calling turns |
|
|
248
|
+
| `model` | Model identifier (e.g., "MiniMax-M2.7") |
|
|
249
|
+
| `usageDetails.input` | Input token count |
|
|
250
|
+
| `usageDetails.output` | Output token count |
|
|
251
|
+
| `usageDetails.total` | Total token count |
|
|
252
|
+
| `costDetails.total` | Total cost in USD |
|
|
253
|
+
| `costDetails.input` | Input cost in USD |
|
|
254
|
+
| `costDetails.output` | Output cost in USD |
|
|
255
|
+
| `metadata.provider` | Provider name |
|
|
256
|
+
| `metadata.requestId` | Provider/Pi request identifier when available |
|
|
257
|
+
| `metadata.status` | HTTP/provider status when available |
|
|
258
|
+
|
|
259
|
+
### Tool Observations
|
|
260
|
+
| Field | Description |
|
|
261
|
+
|-------|-------------|
|
|
262
|
+
| `type` | `tool` |
|
|
263
|
+
| `name` | Tool name (e.g., "bash", "read") |
|
|
264
|
+
| `input` | Tool parameters |
|
|
265
|
+
| `output` | Tool result, shaped and truncated for readability |
|
|
266
|
+
| `metadata.toolCallId` | Stable Pi tool call identifier |
|
|
267
|
+
| `metadata.isError` | Whether the tool failed |
|
|
268
|
+
| `level` | `ERROR` for failed tool calls, otherwise `DEFAULT` |
|
|
269
|
+
|
|
270
|
+
### Observation-Level Scores
|
|
271
|
+
| Score Name | Description |
|
|
272
|
+
|------------|-------------|
|
|
273
|
+
| `tool_is_error` | Value 1 assigned to individual tool observations that errored |
|
|
88
274
|
|
|
89
275
|
## Langfuse Dashboard
|
|
90
276
|
|
|
91
277
|
After running, check your Langfuse project for:
|
|
92
278
|
|
|
93
|
-
1. **Traces**
|
|
94
|
-
2. **Sessions**
|
|
95
|
-
3. **Observations**
|
|
96
|
-
4. **Scores**
|
|
97
|
-
5. **Model Usage**
|
|
279
|
+
1. **Traces** — All pi agent runs with I/O
|
|
280
|
+
2. **Sessions** — Traces grouped by session ID
|
|
281
|
+
3. **Observations** — Tool calls and LLM generations
|
|
282
|
+
4. **Scores** — Evaluation metrics (tool errors, success rate, etc.)
|
|
283
|
+
5. **Model Usage** — Usage breakdown by model
|
|
284
|
+
|
|
285
|
+
You can also monitor your Langfuse data directly from the terminal using the built-in Langfuse skill:
|
|
286
|
+
|
|
287
|
+
```
|
|
288
|
+
/pi-langfuse-langfuse <your-query>
|
|
289
|
+
```
|
|
98
290
|
|
|
99
291
|
## Troubleshooting
|
|
100
292
|
|
|
101
|
-
|
|
102
|
-
- Verify API keys are correct
|
|
103
|
-
- Check Langfuse project is active
|
|
104
|
-
- Ensure API keys have write permissions
|
|
293
|
+
### No traces appearing?
|
|
294
|
+
- Verify API keys are correct — run `/langfuse-setup` to re-configure
|
|
295
|
+
- Check your Langfuse project is active and has write capacity
|
|
296
|
+
- Ensure API keys have write permissions (not read-only)
|
|
297
|
+
- Look for `📊 Langfuse:` log messages in the Pi output
|
|
298
|
+
|
|
299
|
+
### Extension not loading?
|
|
300
|
+
```bash
|
|
301
|
+
pi list # Verify pi-langfuse is installed
|
|
302
|
+
pi install npm:pi-langfuse # Reinstall if missing
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### "Missing config" message on startup?
|
|
306
|
+
- The extension needs credentials. Use the interactive `/langfuse-setup` command
|
|
307
|
+
- Or set `LANGFUSE_PUBLIC_KEY` and `LANGFUSE_SECRET_KEY` environment variables
|
|
105
308
|
|
|
106
|
-
|
|
107
|
-
-
|
|
108
|
-
-
|
|
309
|
+
### Model/cost not showing?
|
|
310
|
+
- Not all providers expose cost information
|
|
311
|
+
- Check the Langfuse traces API for raw observation data
|
|
312
|
+
- The `model` field in generations comes from provider events, finalized assistant messages, `model_select`, or `ctx.model`
|
|
109
313
|
|
|
110
|
-
|
|
111
|
-
-
|
|
112
|
-
-
|
|
314
|
+
### API key errors?
|
|
315
|
+
- Langfuse public keys start with `pk-lf-`, secret keys with `sk-lf-`
|
|
316
|
+
- If self-hosting, verify your host URL is correct
|
|
113
317
|
|
|
114
318
|
## Dependencies
|
|
115
319
|
|
|
116
|
-
- [langfuse](https://www.npmjs.com/package/
|
|
117
|
-
- [@
|
|
320
|
+
- [@langfuse/tracing](https://www.npmjs.com/package/@langfuse/tracing) — Langfuse observation API for `agent`, `generation`, and `tool` traces
|
|
321
|
+
- [@langfuse/otel](https://www.npmjs.com/package/@langfuse/otel) — OpenTelemetry span processor for exporting traces to Langfuse
|
|
322
|
+
- [@langfuse/client](https://www.npmjs.com/package/@langfuse/client) — Langfuse API client used for scores
|
|
323
|
+
- [@opentelemetry/sdk-node](https://www.npmjs.com/package/@opentelemetry/sdk-node) — Node OpenTelemetry SDK
|
|
324
|
+
- [@earendil-works/pi-coding-agent](https://www.npmjs.com/package/@earendil-works/pi-coding-agent) — Pi extension API (peer dependency)
|
|
325
|
+
|
|
326
|
+
## About Langfuse Skill
|
|
327
|
+
|
|
328
|
+
This package includes a Langfuse CLI skill (at `.agents/skills/langfuse/`) that lets you query Langfuse data directly from Pi. Use it to look up traces, prompts, datasets, and scores without leaving the terminal. The skill is auto-registered when the extension is installed globally.
|
|
118
329
|
|
|
119
330
|
## License
|
|
120
331
|
|