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