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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-langfuse",
3
- "version": "1.3.1",
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
- export async function ensureConfig(ctx: any): Promise<boolean> {
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("📊 Langfuse: Missing config. Run this extension in Pi UI to complete setup, or set LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY / LANGFUSE_BASE_URL.");
61
- return false;
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 false;
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 false;
62
+ return null;
76
63
  }
77
64
 
78
65
  const hostInput = (await ctx.ui.input("Langfuse host:", DEFAULT_LANGFUSE_HOST))?.trim();
79
- state.config = {
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
- return ensureConfig(ctx);
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 [{ NodeSDK }, { LangfuseSpanProcessor }, tracing, { LangfuseClient }] = await Promise.all([
13
- import("@opentelemetry/sdk-node"),
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 sdk = new NodeSDK({ spanProcessors: [spanProcessor] });
25
- sdk.start();
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
- sdk,
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.spanProcessor?.forceFlush?.();
52
- await runtime.spanProcessor?.shutdown?.();
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
- sdk?: { start?: () => void; shutdown?: () => Promise<void> };
65
+ tracerProvider?: { forceFlush?: () => Promise<void>; shutdown?: () => Promise<void> };
66
+ clearTracerProvider?: () => void;
66
67
  }
67
68
 
68
69
  export interface GenerationState {