anthropic-payload-log mvp
Added a dedicated Anthropic payload logger that writes exact request JSON (as sent) plus per‑run usage stats (input/output/cache read/write) to a standalone JSONL file, gated by an env flag. Changes - New logger: src/agents/anthropic-payload-log.ts (writes logs/anthropic-payload.jsonl under the state dir, optional override via env). - Hooked into embedded runs to wrap the stream function and record usage: src/agents/pi-embedded-runner/run/attempt.ts. How to enable - CLAWDBOT_ANTHROPIC_PAYLOAD_LOG=1 - Optional: CLAWDBOT_ANTHROPIC_PAYLOAD_LOG_FILE=/path/to/anthropic-payload.jsonl What you’ll get (JSONL) - stage: "request" with payload (exact Anthropic params) + payloadDigest - stage: "usage" with usage (input/output/cacheRead/cacheWrite/totalTokens/etc.) Notes - Usage is taken from the last assistant message in the run; if the run fails before usage is present, you’ll only see an error field. Files touched - src/agents/anthropic-payload-log.ts - src/agents/pi-embedded-runner/run/attempt.ts Tests not run.
This commit is contained in:
committed by
Peter Steinberger
parent
6bd6ae41b1
commit
7e498ab94a
@@ -20,6 +20,7 @@ import { isReasoningTagProvider } from "../../../utils/provider-utils.js";
|
||||
import { isSubagentSessionKey } from "../../../routing/session-key.js";
|
||||
import { resolveUserPath } from "../../../utils.js";
|
||||
import { createCacheTrace } from "../../cache-trace.js";
|
||||
import { createAnthropicPayloadLogger } from "../../anthropic-payload-log.js";
|
||||
import { resolveClawdbotAgentDir } from "../../agent-paths.js";
|
||||
import { resolveSessionAgentIds } from "../../agent-scope.js";
|
||||
import { makeBootstrapWarn, resolveBootstrapContextForRun } from "../../bootstrap-files.js";
|
||||
@@ -458,6 +459,16 @@ export async function runEmbeddedAttempt(
|
||||
modelApi: params.model.api,
|
||||
workspaceDir: params.workspaceDir,
|
||||
});
|
||||
const anthropicPayloadLogger = createAnthropicPayloadLogger({
|
||||
env: process.env,
|
||||
runId: params.runId,
|
||||
sessionId: activeSession.sessionId,
|
||||
sessionKey: params.sessionKey,
|
||||
provider: params.provider,
|
||||
modelId: params.modelId,
|
||||
modelApi: params.model.api,
|
||||
workspaceDir: params.workspaceDir,
|
||||
});
|
||||
|
||||
// Force a stable streamFn reference so vitest can reliably mock @mariozechner/pi-ai.
|
||||
activeSession.agent.streamFn = streamSimple;
|
||||
@@ -478,6 +489,11 @@ export async function runEmbeddedAttempt(
|
||||
});
|
||||
activeSession.agent.streamFn = cacheTrace.wrapStreamFn(activeSession.agent.streamFn);
|
||||
}
|
||||
if (anthropicPayloadLogger) {
|
||||
activeSession.agent.streamFn = anthropicPayloadLogger.wrapStreamFn(
|
||||
activeSession.agent.streamFn,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const prior = await sanitizeSessionHistory({
|
||||
@@ -772,6 +788,7 @@ export async function runEmbeddedAttempt(
|
||||
messages: messagesSnapshot,
|
||||
note: promptError ? "prompt error" : undefined,
|
||||
});
|
||||
anthropicPayloadLogger?.recordUsage(messagesSnapshot, promptError);
|
||||
|
||||
// Run agent_end hooks to allow plugins to analyze the conversation
|
||||
// This is fire-and-forget, so we don't await
|
||||
|
||||
Reference in New Issue
Block a user