fix: add diagnostics cache trace config (#1370) (thanks @parubets)

This commit is contained in:
Peter Steinberger
2026-01-21 10:21:47 +00:00
parent 5392fa0dfa
commit 97e8f9d619
8 changed files with 160 additions and 16 deletions

View File

@@ -0,0 +1,93 @@
import { describe, expect, it } from "vitest";
import type { ClawdbotConfig } from "../config/config.js";
import { resolveUserPath } from "../utils.js";
import { createCacheTrace } from "./cache-trace.js";
describe("createCacheTrace", () => {
it("returns null when diagnostics cache tracing is disabled", () => {
const trace = createCacheTrace({
cfg: {} as ClawdbotConfig,
env: {},
});
expect(trace).toBeNull();
});
it("honors diagnostics cache trace config and expands file paths", () => {
const lines: string[] = [];
const trace = createCacheTrace({
cfg: {
diagnostics: {
cacheTrace: {
enabled: true,
filePath: "~/.clawdbot/logs/cache-trace.jsonl",
},
},
},
env: {},
writer: {
filePath: "memory",
write: (line) => lines.push(line),
},
});
expect(trace).not.toBeNull();
expect(trace?.filePath).toBe(resolveUserPath("~/.clawdbot/logs/cache-trace.jsonl"));
trace?.recordStage("session:loaded", {
messages: [],
system: "sys",
});
expect(lines.length).toBe(1);
});
it("records empty prompt/system values when enabled", () => {
const lines: string[] = [];
const trace = createCacheTrace({
cfg: {
diagnostics: {
cacheTrace: {
enabled: true,
includePrompt: true,
includeSystem: true,
},
},
},
env: {},
writer: {
filePath: "memory",
write: (line) => lines.push(line),
},
});
trace?.recordStage("prompt:before", { prompt: "", system: "" });
const event = JSON.parse(lines[0]?.trim() ?? "{}") as Record<string, unknown>;
expect(event.prompt).toBe("");
expect(event.system).toBe("");
});
it("respects env overrides for enablement", () => {
const lines: string[] = [];
const trace = createCacheTrace({
cfg: {
diagnostics: {
cacheTrace: {
enabled: true,
},
},
},
env: {
CLAWDBOT_CACHE_TRACE: "0",
},
writer: {
filePath: "memory",
write: (line) => lines.push(line),
},
});
expect(trace).toBeNull();
});
});

View File

@@ -7,8 +7,8 @@ import type { Api, Model } from "@mariozechner/pi-ai";
import type { ClawdbotConfig } from "../config/config.js";
import { resolveStateDir } from "../config/paths.js";
import { isTruthyEnvValue } from "../infra/env.js";
import { parseBooleanValue } from "../utils/boolean.js";
import { resolveUserPath } from "../utils.js";
export type CacheTraceStage =
| "session:loaded"
@@ -61,6 +61,7 @@ type CacheTraceInit = {
modelId?: string;
modelApi?: string | null;
workspaceDir?: string;
writer?: CacheTraceWriter;
};
type CacheTraceConfig = {
@@ -80,14 +81,18 @@ const writers = new Map<string, CacheTraceWriter>();
function resolveCacheTraceConfig(params: CacheTraceInit): CacheTraceConfig {
const env = params.env ?? process.env;
const enabled = isTruthyEnvValue(env.CLAWDBOT_CACHE_TRACE);
const filePath =
env.CLAWDBOT_CACHE_TRACE_FILE?.trim() ||
path.join(resolveStateDir(env), "logs", "cache-trace.jsonl");
const config = params.cfg?.diagnostics?.cacheTrace;
const envEnabled = parseBooleanValue(env.CLAWDBOT_CACHE_TRACE);
const enabled = envEnabled ?? config?.enabled ?? false;
const fileOverride = config?.filePath?.trim() || env.CLAWDBOT_CACHE_TRACE_FILE?.trim();
const filePath = fileOverride
? resolveUserPath(fileOverride)
: path.join(resolveStateDir(env), "logs", "cache-trace.jsonl");
const includeMessages = parseBooleanValue(env.CLAWDBOT_CACHE_TRACE_MESSAGES);
const includePrompt = parseBooleanValue(env.CLAWDBOT_CACHE_TRACE_PROMPT);
const includeSystem = parseBooleanValue(env.CLAWDBOT_CACHE_TRACE_SYSTEM);
const includeMessages =
parseBooleanValue(env.CLAWDBOT_CACHE_TRACE_MESSAGES) ?? config?.includeMessages;
const includePrompt = parseBooleanValue(env.CLAWDBOT_CACHE_TRACE_PROMPT) ?? config?.includePrompt;
const includeSystem = parseBooleanValue(env.CLAWDBOT_CACHE_TRACE_SYSTEM) ?? config?.includeSystem;
return {
enabled,
@@ -189,7 +194,7 @@ export function createCacheTrace(params: CacheTraceInit): CacheTrace | null {
const cfg = resolveCacheTraceConfig(params);
if (!cfg.enabled) return null;
const writer = getWriter(cfg.filePath);
const writer = params.writer ?? getWriter(cfg.filePath);
let seq = 0;
const base: Omit<CacheTraceEvent, "ts" | "seq" | "stage"> = {
@@ -210,10 +215,10 @@ export function createCacheTrace(params: CacheTraceInit): CacheTrace | null {
stage,
};
if (payload.prompt && cfg.includePrompt) {
if (payload.prompt !== undefined && cfg.includePrompt) {
event.prompt = payload.prompt;
}
if (payload.system && cfg.includeSystem) {
if (payload.system !== undefined && cfg.includeSystem) {
event.system = payload.system;
event.systemDigest = digest(payload.system);
}