pi-langfuse 1.3.1 → 1.3.2
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/package.json +3 -2
- package/src/config.ts +44 -20
- package/src/langfuse.ts +9 -8
- package/src/types.ts +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-langfuse",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "Langfuse extension for Pi coding agent",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"@langfuse/client": "^5.3.0",
|
|
35
35
|
"@langfuse/otel": "^5.3.0",
|
|
36
36
|
"@langfuse/tracing": "^5.3.0",
|
|
37
|
-
"@opentelemetry/sdk-node": "^0.218.0"
|
|
37
|
+
"@opentelemetry/sdk-node": "^0.218.0",
|
|
38
|
+
"@opentelemetry/sdk-trace-base": "^2.0.1"
|
|
38
39
|
},
|
|
39
40
|
"peerDependencies": {
|
|
40
41
|
"@earendil-works/pi-coding-agent": "*"
|
package/src/config.ts
CHANGED
|
@@ -42,23 +42,10 @@ export function saveConfig(config: Config) {
|
|
|
42
42
|
writeFileSync(CONFIG_PATH, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
if (!state.config) {
|
|
47
|
-
state.config = loadConfigFromEnv() || loadConfigFromFile();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (state.config) {
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (state.setupAttemptedThisSession) {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
state.setupAttemptedThisSession = true;
|
|
58
|
-
|
|
45
|
+
async function collectConfigFromUI(ctx: any, reason: string): Promise<Config | null> {
|
|
59
46
|
if (!ctx.hasUI) {
|
|
60
|
-
console.log(
|
|
61
|
-
return
|
|
47
|
+
console.log(`📊 Langfuse: ${reason}. Run this extension in Pi UI to complete setup, or set LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY / LANGFUSE_BASE_URL.`);
|
|
48
|
+
return null;
|
|
62
49
|
}
|
|
63
50
|
|
|
64
51
|
ctx.ui.notify("Langfuse setup required. Enter your API keys to enable tracing.", "info");
|
|
@@ -66,21 +53,25 @@ export async function ensureConfig(ctx: any): Promise<boolean> {
|
|
|
66
53
|
const publicKey = (await ctx.ui.input("Langfuse public key:", "pk-lf-..."))?.trim();
|
|
67
54
|
if (!publicKey) {
|
|
68
55
|
ctx.ui.notify("Langfuse setup cancelled.", "warning");
|
|
69
|
-
return
|
|
56
|
+
return null;
|
|
70
57
|
}
|
|
71
58
|
|
|
72
59
|
const secretKey = (await ctx.ui.input("Langfuse secret key:", "sk-lf-..."))?.trim();
|
|
73
60
|
if (!secretKey) {
|
|
74
61
|
ctx.ui.notify("Langfuse setup cancelled.", "warning");
|
|
75
|
-
return
|
|
62
|
+
return null;
|
|
76
63
|
}
|
|
77
64
|
|
|
78
65
|
const hostInput = (await ctx.ui.input("Langfuse host:", DEFAULT_LANGFUSE_HOST))?.trim();
|
|
79
|
-
|
|
66
|
+
return {
|
|
80
67
|
publicKey,
|
|
81
68
|
secretKey,
|
|
82
69
|
host: hostInput || DEFAULT_LANGFUSE_HOST,
|
|
83
70
|
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function saveConfigFromUI(ctx: any, config: Config): Promise<boolean> {
|
|
74
|
+
state.config = config;
|
|
84
75
|
|
|
85
76
|
try {
|
|
86
77
|
saveConfig(state.config);
|
|
@@ -94,9 +85,42 @@ export async function ensureConfig(ctx: any): Promise<boolean> {
|
|
|
94
85
|
}
|
|
95
86
|
}
|
|
96
87
|
|
|
88
|
+
export async function ensureConfig(ctx: any): Promise<boolean> {
|
|
89
|
+
if (!state.config) {
|
|
90
|
+
state.config = loadConfigFromEnv() || loadConfigFromFile();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (state.config) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (state.setupAttemptedThisSession) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
state.setupAttemptedThisSession = true;
|
|
101
|
+
|
|
102
|
+
const config = await collectConfigFromUI(ctx, "Missing config");
|
|
103
|
+
if (!config) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return saveConfigFromUI(ctx, config);
|
|
108
|
+
}
|
|
109
|
+
|
|
97
110
|
export async function promptForConfig(ctx: any): Promise<boolean> {
|
|
98
111
|
state.setupAttemptedThisSession = false;
|
|
99
112
|
state.config = null;
|
|
100
113
|
await shutdownRuntime();
|
|
101
|
-
|
|
114
|
+
|
|
115
|
+
const config = await collectConfigFromUI(ctx, "Manual setup requested");
|
|
116
|
+
if (!config) {
|
|
117
|
+
state.config = loadConfigFromEnv() || loadConfigFromFile();
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const saved = await saveConfigFromUI(ctx, config);
|
|
122
|
+
if (saved) {
|
|
123
|
+
ctx.ui.notify("Langfuse tracing enabled for future agent runs.", "info");
|
|
124
|
+
}
|
|
125
|
+
return saved;
|
|
102
126
|
}
|
package/src/langfuse.ts
CHANGED
|
@@ -9,8 +9,8 @@ export async function getRuntime(): Promise<LangfuseRuntime> {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
if (!runtime) {
|
|
12
|
-
const [{
|
|
13
|
-
import("@opentelemetry/sdk-
|
|
12
|
+
const [{ BasicTracerProvider }, { LangfuseSpanProcessor }, tracing, { LangfuseClient }] = await Promise.all([
|
|
13
|
+
import("@opentelemetry/sdk-trace-base"),
|
|
14
14
|
import("@langfuse/otel"),
|
|
15
15
|
import("@langfuse/tracing"),
|
|
16
16
|
import("@langfuse/client"),
|
|
@@ -21,8 +21,8 @@ export async function getRuntime(): Promise<LangfuseRuntime> {
|
|
|
21
21
|
secretKey: state.config.secretKey,
|
|
22
22
|
baseUrl: state.config.host,
|
|
23
23
|
});
|
|
24
|
-
const
|
|
25
|
-
|
|
24
|
+
const tracerProvider = new BasicTracerProvider({ spanProcessors: [spanProcessor] });
|
|
25
|
+
tracing.setLangfuseTracerProvider(tracerProvider);
|
|
26
26
|
|
|
27
27
|
runtime = {
|
|
28
28
|
startObservation: tracing.startObservation as unknown as LangfuseRuntime["startObservation"],
|
|
@@ -33,7 +33,8 @@ export async function getRuntime(): Promise<LangfuseRuntime> {
|
|
|
33
33
|
baseUrl: state.config.host,
|
|
34
34
|
}) as LangfuseScoreClient,
|
|
35
35
|
spanProcessor,
|
|
36
|
-
|
|
36
|
+
tracerProvider,
|
|
37
|
+
clearTracerProvider: () => tracing.setLangfuseTracerProvider(null),
|
|
37
38
|
};
|
|
38
39
|
}
|
|
39
40
|
|
|
@@ -48,12 +49,12 @@ export async function shutdownRuntime(): Promise<void> {
|
|
|
48
49
|
try {
|
|
49
50
|
await runtime.scoreClient.flush?.();
|
|
50
51
|
await runtime.scoreClient.shutdown?.();
|
|
51
|
-
await runtime.
|
|
52
|
-
await runtime.
|
|
53
|
-
await runtime.sdk?.shutdown?.();
|
|
52
|
+
await runtime.tracerProvider?.forceFlush?.();
|
|
53
|
+
await runtime.tracerProvider?.shutdown?.();
|
|
54
54
|
} catch (e) {
|
|
55
55
|
console.warn("📊 Langfuse: Failed to flush/shutdown cleanly", e);
|
|
56
56
|
} finally {
|
|
57
|
+
runtime.clearTracerProvider?.();
|
|
57
58
|
runtime = null;
|
|
58
59
|
}
|
|
59
60
|
}
|
package/src/types.ts
CHANGED
|
@@ -62,7 +62,8 @@ export interface LangfuseRuntime {
|
|
|
62
62
|
) => LangfuseObservation;
|
|
63
63
|
scoreClient: LangfuseScoreClient;
|
|
64
64
|
spanProcessor?: { forceFlush?: () => Promise<void>; shutdown?: () => Promise<void> };
|
|
65
|
-
|
|
65
|
+
tracerProvider?: { forceFlush?: () => Promise<void>; shutdown?: () => Promise<void> };
|
|
66
|
+
clearTracerProvider?: () => void;
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
export interface GenerationState {
|