Skip to content

Commit 0138d11

Browse files
authored
feat(tracing): add session trace metadata (#92)
Record the pi version, run mode, and session display name on root spans so Braintrust traces are easier to identify across pi releases and execution modes. Use the session display name as the root span name when one is available, while preserving the existing workspace-based fallback.
1 parent a6f2e32 commit 0138d11

2 files changed

Lines changed: 45 additions & 6 deletions

File tree

src/index.test.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,9 @@ async function createHarness() {
159159
sessionManager: {
160160
getSessionFile: () => "/tmp/session.json",
161161
getSessionId: () => "session-1",
162+
getSessionName: () => "Checkout fix",
162163
},
164+
mode: "json",
163165
};
164166

165167
async function emit(eventName: string, event: Record<string, unknown> = {}): Promise<void> {
@@ -244,6 +246,27 @@ describe("braintrustPiExtension", () => {
244246
expect(mockState.updateSpans).toEqual([]);
245247
});
246248

249+
it("annotates root spans with pi version, mode, and session name metadata", async () => {
250+
const { emit } = await createHarness();
251+
252+
await emit("before_agent_start", {
253+
prompt: "Inspect the package",
254+
images: [],
255+
});
256+
257+
expect(mockState.startSpans[0]).toMatchObject({
258+
name: "Checkout fix",
259+
type: "task",
260+
metadata: {
261+
source: "pi",
262+
extension_version: packageVersion,
263+
pi_version: expect.any(String),
264+
pi_mode: "json",
265+
session_name: "Checkout fix",
266+
},
267+
});
268+
});
269+
247270
it("annotates turn spans with idle input event metadata", async () => {
248271
const { emit } = await createHarness();
249272

@@ -370,7 +393,7 @@ describe("braintrustPiExtension", () => {
370393
});
371394

372395
const rootSpan = mockState.startSpans.find(
373-
(span) => span.type === "task" && String(span.name).startsWith("pi:"),
396+
(span) => span.type === "task" && span.parentSpanId === undefined,
374397
);
375398
const compactionSpan = mockState.startSpans.find((span) => span.name === "Compaction");
376399

@@ -513,7 +536,9 @@ describe("braintrustPiExtension", () => {
513536
sessionManager: {
514537
getSessionFile: () => "/tmp/session.json",
515538
getSessionId: () => "session-1",
539+
getSessionName: () => undefined,
516540
},
541+
mode: "tui",
517542
};
518543

519544
const emit = async (eventName: string, event: Record<string, unknown> = {}): Promise<void> => {

src/index.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { hostname, userInfo } from "node:os";
22
import { basename, resolve } from "node:path";
3-
import type {
4-
AgentEndEvent,
5-
ExtensionAPI,
6-
ExtensionContext,
3+
import {
4+
VERSION as PI_VERSION,
5+
type AgentEndEvent,
6+
type ExtensionAPI,
7+
type ExtensionContext,
78
} from "@earendil-works/pi-coding-agent";
89
import { BraintrustClient, type BraintrustSpanHandle } from "./client.ts";
910
import { createLogger, loadConfig } from "./config.ts";
@@ -241,12 +242,25 @@ function findLastAssistant(
241242
return undefined;
242243
}
243244

245+
function getSessionName(ctx: ExtensionContext): string | undefined {
246+
try {
247+
const name = ctx.sessionManager.getSessionName?.();
248+
return typeof name === "string" && name.trim() ? name : undefined;
249+
} catch {
250+
return undefined;
251+
}
252+
}
253+
244254
function standardRootMetadata(ctx: ExtensionContext, config: TraceConfig): Record<string, unknown> {
245255
const descriptor = getSessionDescriptor(ctx);
256+
const sessionName = getSessionName(ctx);
246257
return {
247258
...config.additionalMetadata,
248259
source: "pi",
249260
extension_version: EXTENSION_VERSION,
261+
pi_version: PI_VERSION,
262+
pi_mode: ctx.mode,
263+
session_name: sessionName,
250264
session_id: descriptor.sessionId,
251265
session_key: descriptor.sessionKey,
252266
session_file: descriptor.sessionFile,
@@ -487,7 +501,7 @@ export default function braintrustPiExtension(pi: ExtensionAPI): void {
487501
rootSpanId: traceRootSpanId,
488502
parentSpanId,
489503
startedAt,
490-
name: rootSpanName(ctx.cwd),
504+
name: getSessionName(ctx) ?? rootSpanName(ctx.cwd),
491505
type: "task",
492506
metadata: {
493507
...standardRootMetadata(ctx, config),

0 commit comments

Comments
 (0)