pi-langfuse 1.5.9 → 1.5.11
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/index.ts +16 -5
- package/package.json +1 -1
- package/src/handlers/agent.ts +44 -14
- package/src/langfuse.ts +3 -0
- package/src/types.ts +1 -0
- package/types/pi-coding-agent.d.ts +7 -0
package/index.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { basename } from "node:path";
|
|
11
|
-
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
11
|
+
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
12
12
|
|
|
13
13
|
import { state, resetRunState, runWithSession, setCurrentSession } from "./src/state.js";
|
|
14
14
|
import { ensureConfig, promptForConfig, loadConfig } from "./src/config.js";
|
|
@@ -16,7 +16,7 @@ import { shutdownRuntime } from "./src/langfuse.js";
|
|
|
16
16
|
import { handleLangfusePrivacyCommand, handleLangfuseStatusCommand, handleLangfuseTestCommand } from "./src/commands.js";
|
|
17
17
|
import { getMessageFromEvent, extractAssistantOutput, getCapturePolicy } from "./src/utils.js";
|
|
18
18
|
import { applyCapturePolicy } from "./src/capture-policy.js";
|
|
19
|
-
import { startAgentRun, finishAgentRun } from "./src/handlers/agent.js";
|
|
19
|
+
import { startAgentRun, finishAgentRun, recordSystemPrompt } from "./src/handlers/agent.js";
|
|
20
20
|
import { startTurnObservation, finishTurnObservation } from "./src/handlers/turn.js";
|
|
21
21
|
import {
|
|
22
22
|
startGeneration,
|
|
@@ -74,10 +74,18 @@ export default async function (pi: ExtensionAPI) {
|
|
|
74
74
|
},
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
-
const getSessionId = (ctx?:
|
|
77
|
+
const getSessionId = (ctx?: unknown): string | undefined => {
|
|
78
78
|
try {
|
|
79
|
-
const
|
|
80
|
-
|
|
79
|
+
const sessionManager = (ctx as ExtensionContext | undefined)?.sessionManager;
|
|
80
|
+
const sessionId = sessionManager?.getSessionId?.();
|
|
81
|
+
if (typeof sessionId === "string" && sessionId) {
|
|
82
|
+
return sessionId;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const sessionFile = sessionManager?.getSessionFile?.();
|
|
86
|
+
return typeof sessionFile === "string" && sessionFile
|
|
87
|
+
? basename(sessionFile, ".jsonl")
|
|
88
|
+
: undefined;
|
|
81
89
|
} catch {
|
|
82
90
|
return undefined;
|
|
83
91
|
}
|
|
@@ -104,6 +112,9 @@ export default async function (pi: ExtensionAPI) {
|
|
|
104
112
|
if (!state.agentState?.root) {
|
|
105
113
|
await startAgentRun(event, ctx);
|
|
106
114
|
}
|
|
115
|
+
// The system prompt is only final here: before_agent_start handlers that
|
|
116
|
+
// run after this extension may still rewrite it.
|
|
117
|
+
await recordSystemPrompt(ctx);
|
|
107
118
|
}));
|
|
108
119
|
|
|
109
120
|
pi.on("turn_start", async (event, ctx) => withSession(ctx, async () => {
|
package/package.json
CHANGED
package/src/handlers/agent.ts
CHANGED
|
@@ -54,15 +54,6 @@ export async function startAgentRun(event: Record<string, unknown>, ctx: any) {
|
|
|
54
54
|
state.currentProvider = ctx.model.provider || "";
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
let systemPrompt = undefined;
|
|
58
|
-
try {
|
|
59
|
-
if (ctx.getSystemPrompt) {
|
|
60
|
-
systemPrompt = await ctx.getSystemPrompt();
|
|
61
|
-
}
|
|
62
|
-
} catch {
|
|
63
|
-
// Ignore if getSystemPrompt is not available or fails
|
|
64
|
-
}
|
|
65
|
-
|
|
66
57
|
const rawPromptInput = shapePayload({
|
|
67
58
|
prompt: event.prompt,
|
|
68
59
|
images: event.images,
|
|
@@ -79,7 +70,6 @@ export async function startAgentRun(event: Record<string, unknown>, ctx: any) {
|
|
|
79
70
|
...(state.currentProvider ? { provider: state.currentProvider } : {}),
|
|
80
71
|
sessionId: state.currentSessionId || undefined,
|
|
81
72
|
},
|
|
82
|
-
systemPrompt: systemPrompt ? truncate(String(systemPrompt), getLimits().maxString) : undefined,
|
|
83
73
|
},
|
|
84
74
|
getCapturePolicy(),
|
|
85
75
|
);
|
|
@@ -106,10 +96,7 @@ export async function startAgentRun(event: Record<string, unknown>, ctx: any) {
|
|
|
106
96
|
"pi-agent",
|
|
107
97
|
{
|
|
108
98
|
input: captured.input,
|
|
109
|
-
metadata: {
|
|
110
|
-
...(captured.metadata ?? {}),
|
|
111
|
-
...(captured.systemPrompt ? { systemPrompt: captured.systemPrompt } : {}),
|
|
112
|
-
},
|
|
99
|
+
metadata: captured.metadata ?? {},
|
|
113
100
|
},
|
|
114
101
|
{ asType: "agent" },
|
|
115
102
|
),
|
|
@@ -124,6 +111,49 @@ export async function startAgentRun(event: Record<string, unknown>, ctx: any) {
|
|
|
124
111
|
}
|
|
125
112
|
}
|
|
126
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Records the effective system prompt on the root agent observation.
|
|
116
|
+
*
|
|
117
|
+
* Deliberately called from `agent_start` rather than `before_agent_start`:
|
|
118
|
+
* during `before_agent_start` the extension runner hands each handler the
|
|
119
|
+
* prompt as it stands mid-chain, so extensions registered after this one
|
|
120
|
+
* (e.g. inline factories that rewrite the system prompt) are not reflected
|
|
121
|
+
* yet. By `agent_start` the session has applied the final override, and
|
|
122
|
+
* `ctx.getSystemPrompt()` returns the prompt actually sent to the model.
|
|
123
|
+
*/
|
|
124
|
+
export async function recordSystemPrompt(ctx: any) {
|
|
125
|
+
const root = state.agentState?.root;
|
|
126
|
+
if (state.isTracingDisabled || !root) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let systemPrompt = undefined;
|
|
131
|
+
try {
|
|
132
|
+
if (ctx.getSystemPrompt) {
|
|
133
|
+
systemPrompt = await ctx.getSystemPrompt();
|
|
134
|
+
}
|
|
135
|
+
} catch {
|
|
136
|
+
// Ignore if getSystemPrompt is not available or fails
|
|
137
|
+
}
|
|
138
|
+
if (!systemPrompt) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const captured = applyCapturePolicy(
|
|
143
|
+
{ systemPrompt: truncate(String(systemPrompt), getLimits().maxString) },
|
|
144
|
+
getCapturePolicy(),
|
|
145
|
+
);
|
|
146
|
+
if (!captured.systemPrompt) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
root.update({ metadata: { systemPrompt: captured.systemPrompt } });
|
|
152
|
+
} catch (e) {
|
|
153
|
+
console.warn("\u{1F4CA} Langfuse: Failed to record system prompt", e);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
127
157
|
export async function finishAgentRun(event: Record<string, unknown> = {}) {
|
|
128
158
|
if (!state.agentState?.root) {
|
|
129
159
|
resetRunState();
|
package/src/langfuse.ts
CHANGED
|
@@ -219,6 +219,9 @@ async function flushPendingScores(rt: LangfuseRuntime, signal: AbortSignal): Pro
|
|
|
219
219
|
|
|
220
220
|
while (pendingScores.length > 0) {
|
|
221
221
|
const scores = pendingScores.slice(0, MAX_SCORE_BATCH_SIZE);
|
|
222
|
+
for (const score of scores) {
|
|
223
|
+
score.id ??= randomUUID();
|
|
224
|
+
}
|
|
222
225
|
try {
|
|
223
226
|
const errors = await ingestBatch(
|
|
224
227
|
rt,
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
declare module "@earendil-works/pi-coding-agent" {
|
|
2
|
+
export interface ExtensionContext {
|
|
3
|
+
sessionManager?: {
|
|
4
|
+
getSessionId?: () => unknown;
|
|
5
|
+
getSessionFile?: () => unknown;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
|
|
2
9
|
export interface ExtensionAPI {
|
|
3
10
|
on(event: string, handler: (event: any, ctx: any) => unknown): void;
|
|
4
11
|
registerCommand(
|