@braintrust/pi-extension 0.5.0 → 0.5.1
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 +2 -2
- package/package.json +6 -5
- package/src/config.test.ts +31 -4
- package/src/config.ts +14 -3
- package/src/index.integration.test.ts +3 -3
- package/src/index.test.ts +5 -0
- package/src/index.ts +7 -3
- package/src/version.ts +2 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@braintrust/pi-extension)
|
|
4
4
|
|
|
5
|
-
Braintrust extension for [pi](https://github.com/
|
|
5
|
+
Braintrust extension for [pi](https://github.com/earendil-works/pi-coding-agent).
|
|
6
6
|
|
|
7
7
|
Today this extension automatically traces pi sessions, turns, model calls, and tool executions to Braintrust.
|
|
8
8
|
|
|
@@ -47,7 +47,7 @@ pi -e .
|
|
|
47
47
|
|
|
48
48
|
## Compatibility
|
|
49
49
|
|
|
50
|
-
This package supports the **latest patch release from each of the last
|
|
50
|
+
This package supports the **latest patch release from each of the last five stable pi minor versions**, currently excluding pi versions before `0.65.0`.
|
|
51
51
|
|
|
52
52
|
Our GitHub Actions compatibility job automatically resolves and tests that compatibility window, so new pi releases are picked up without manually updating the matrix.
|
|
53
53
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@braintrust/pi-extension",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Braintrust extension for pi. Includes automatic tracing for pi sessions, turns, LLM calls, and tool executions to Braintrust.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"braintrust",
|
|
@@ -28,15 +28,15 @@
|
|
|
28
28
|
"valibot": "^1.3.1"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
31
|
+
"@earendil-works/pi-ai": "^0.74.0",
|
|
32
|
+
"@earendil-works/pi-coding-agent": "^0.74.0",
|
|
33
33
|
"@types/node": "^25.6.0",
|
|
34
34
|
"typescript": "^6.0.2",
|
|
35
35
|
"vite-plus": "^0.1.16",
|
|
36
36
|
"vitest": "^4.1.4"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@
|
|
39
|
+
"@earendil-works/pi-coding-agent": "*"
|
|
40
40
|
},
|
|
41
41
|
"devEngines": {
|
|
42
42
|
"packageManager": {
|
|
@@ -57,10 +57,11 @@
|
|
|
57
57
|
},
|
|
58
58
|
"scripts": {
|
|
59
59
|
"preinstall": "node -e \"const userAgent = process.env.npm_config_user_agent || ''; if (process.env.INIT_CWD === process.cwd() && !userAgent.includes('pnpm/')) { console.error('Use pnpm in this repo.'); process.exit(1); }\"",
|
|
60
|
-
"check": "vp check",
|
|
60
|
+
"check": "node scripts/sync-version.mjs --check && vp check",
|
|
61
61
|
"fmt": "vp fmt",
|
|
62
62
|
"lint": "vp lint",
|
|
63
63
|
"pack": "vp pack",
|
|
64
|
+
"sync:version": "node scripts/sync-version.mjs",
|
|
64
65
|
"test": "vitest run",
|
|
65
66
|
"test:integration": "vitest run src/index.integration.test.ts",
|
|
66
67
|
"test:watch": "vitest",
|
package/src/config.test.ts
CHANGED
|
@@ -324,9 +324,8 @@ describe("loadConfig", () => {
|
|
|
324
324
|
});
|
|
325
325
|
|
|
326
326
|
describe("createLogger", () => {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
const config: TraceConfig = {
|
|
327
|
+
function makeLoggerConfig(overrides: Partial<TraceConfig> = {}): TraceConfig {
|
|
328
|
+
return {
|
|
330
329
|
enabled: true,
|
|
331
330
|
apiKey: "key",
|
|
332
331
|
apiUrl: undefined,
|
|
@@ -335,14 +334,19 @@ describe("createLogger", () => {
|
|
|
335
334
|
projectName: "pi",
|
|
336
335
|
debug: true,
|
|
337
336
|
logFile: undefined,
|
|
338
|
-
stateDir,
|
|
337
|
+
stateDir: makeTempDir("pi-extension-state-"),
|
|
339
338
|
additionalMetadata: {},
|
|
340
339
|
parentSpanId: undefined,
|
|
341
340
|
rootSpanId: undefined,
|
|
342
341
|
showUi: true,
|
|
343
342
|
showTraceLink: true,
|
|
344
343
|
configIssues: [],
|
|
344
|
+
...overrides,
|
|
345
345
|
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
it("writes json log lines to the default log file when debug is enabled", async () => {
|
|
349
|
+
const config = makeLoggerConfig();
|
|
346
350
|
|
|
347
351
|
const logger = createLogger(config);
|
|
348
352
|
logger.debug("debug message", { nested: { value: 1 } });
|
|
@@ -361,4 +365,27 @@ describe("createLogger", () => {
|
|
|
361
365
|
message: "warn message",
|
|
362
366
|
});
|
|
363
367
|
});
|
|
368
|
+
|
|
369
|
+
it("writes warnings and errors to the default log file when debug is disabled", async () => {
|
|
370
|
+
const config = makeLoggerConfig({ debug: false, logFile: undefined });
|
|
371
|
+
const logger = createLogger(config);
|
|
372
|
+
|
|
373
|
+
logger.debug("debug message");
|
|
374
|
+
logger.info("info message");
|
|
375
|
+
logger.warn("warn message", { reason: "test" });
|
|
376
|
+
logger.error("error message");
|
|
377
|
+
await logger.flush();
|
|
378
|
+
|
|
379
|
+
const lines = readFileSync(logger.filePath, "utf8").trim().split("\n");
|
|
380
|
+
expect(lines).toHaveLength(2);
|
|
381
|
+
expect(JSON.parse(lines[0])).toMatchObject({
|
|
382
|
+
level: "warn",
|
|
383
|
+
message: "warn message",
|
|
384
|
+
data: { reason: "test" },
|
|
385
|
+
});
|
|
386
|
+
expect(JSON.parse(lines[1])).toMatchObject({
|
|
387
|
+
level: "error",
|
|
388
|
+
message: "error message",
|
|
389
|
+
});
|
|
390
|
+
});
|
|
364
391
|
});
|
package/src/config.ts
CHANGED
|
@@ -450,14 +450,25 @@ export function createLogger(config: TraceConfig): Logger {
|
|
|
450
450
|
config.logFile && config.logFile !== "true" && config.logFile !== "auto"
|
|
451
451
|
? config.logFile
|
|
452
452
|
: join(config.stateDir, "braintrust-pi-extension.log");
|
|
453
|
-
const
|
|
453
|
+
const infoLoggingEnabled = config.debug || Boolean(config.logFile);
|
|
454
454
|
|
|
455
|
-
|
|
455
|
+
let logDirEnsured = false;
|
|
456
|
+
|
|
457
|
+
function shouldLog(level: LogLevel): boolean {
|
|
458
|
+
return level === "warn" || level === "error" || infoLoggingEnabled;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function ensureLogDir(): void {
|
|
462
|
+
if (logDirEnsured) return;
|
|
463
|
+
ensureDir(dirname(explicitLogFile));
|
|
464
|
+
logDirEnsured = true;
|
|
465
|
+
}
|
|
456
466
|
|
|
457
467
|
let pendingWrite = Promise.resolve();
|
|
458
468
|
|
|
459
469
|
function emit(level: LogLevel, message: string, data?: unknown): void {
|
|
460
|
-
if (!
|
|
470
|
+
if (!shouldLog(level)) return;
|
|
471
|
+
ensureLogDir();
|
|
461
472
|
pendingWrite = pendingWrite
|
|
462
473
|
.catch(() => {})
|
|
463
474
|
.then(async () => {
|
|
@@ -11,14 +11,14 @@ import {
|
|
|
11
11
|
type Model,
|
|
12
12
|
type SimpleStreamOptions,
|
|
13
13
|
type ToolCall,
|
|
14
|
-
} from "@
|
|
15
|
-
import * as piCodingAgent from "@
|
|
14
|
+
} from "@earendil-works/pi-ai";
|
|
15
|
+
import * as piCodingAgent from "@earendil-works/pi-coding-agent";
|
|
16
16
|
import {
|
|
17
17
|
createAgentSession,
|
|
18
18
|
DefaultResourceLoader,
|
|
19
19
|
SessionManager,
|
|
20
20
|
type ExtensionAPI,
|
|
21
|
-
} from "@
|
|
21
|
+
} from "@earendil-works/pi-coding-agent";
|
|
22
22
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
23
23
|
import braintrustPiExtension from "./index.ts";
|
|
24
24
|
|
package/src/index.test.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
1
2
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
3
|
|
|
4
|
+
const packageVersion = (JSON.parse(readFileSync("package.json", "utf8")) as { version: string })
|
|
5
|
+
.version;
|
|
6
|
+
|
|
3
7
|
const mockState = vi.hoisted(() => ({
|
|
4
8
|
startSpans: [] as Array<Record<string, unknown>>,
|
|
5
9
|
logSpans: [] as Array<Record<string, unknown>>,
|
|
@@ -193,6 +197,7 @@ describe("braintrustPiExtension", () => {
|
|
|
193
197
|
expect(mockState.widgets.at(-1)?.content?.[1]).toBe(
|
|
194
198
|
"braintrust.dev/app/test-org/p/pi/logs?oid=trace-row-1",
|
|
195
199
|
);
|
|
200
|
+
expect(mockState.startSpans[0]?.metadata).toMatchObject({ extension_version: packageVersion });
|
|
196
201
|
|
|
197
202
|
await emit("session_shutdown");
|
|
198
203
|
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { basename, resolve } from "node:path";
|
|
2
1
|
import { hostname, userInfo } from "node:os";
|
|
3
|
-
import
|
|
2
|
+
import { basename, resolve } from "node:path";
|
|
3
|
+
import type {
|
|
4
|
+
AgentEndEvent,
|
|
5
|
+
ExtensionAPI,
|
|
6
|
+
ExtensionContext,
|
|
7
|
+
} from "@earendil-works/pi-coding-agent";
|
|
4
8
|
import { BraintrustClient, type BraintrustSpanHandle } from "./client.ts";
|
|
5
9
|
import { createLogger, loadConfig } from "./config.ts";
|
|
6
10
|
import { createStateStore } from "./state.ts";
|
|
@@ -13,6 +17,7 @@ import type {
|
|
|
13
17
|
NormalizedAssistantMessage,
|
|
14
18
|
TraceConfig,
|
|
15
19
|
} from "./types.ts";
|
|
20
|
+
import { EXTENSION_VERSION } from "./version.ts";
|
|
16
21
|
import {
|
|
17
22
|
buildTurnInput,
|
|
18
23
|
extractErrorText,
|
|
@@ -29,7 +34,6 @@ import {
|
|
|
29
34
|
toUnixSeconds,
|
|
30
35
|
} from "./utils.ts";
|
|
31
36
|
|
|
32
|
-
const EXTENSION_VERSION = "0.1.0";
|
|
33
37
|
const TRACING_STATUS_KEY = "braintrust-tracing";
|
|
34
38
|
const TRACING_WIDGET_KEY = "braintrust-trace-link";
|
|
35
39
|
|
package/src/version.ts
ADDED