mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-23 19:08:22 -06:00
f53346944d
* feat: correlate native search outcomes in audit history Metadata-only audit ledger for agent runs and tool actions in the shared state DB: stable event identity, closed action/status/error vocabularies, one-way-hashed tool-call ids, never-inferred terminal outcomes for native web-search (explicit completed/failed only; otherwise unknown), bounded retention, audit.list gateway RPC and openclaw audit CLI. Squashed from the 82-commit audit stack for replay onto current main. * feat(audit): add audit.enabled config gate (default on) The metadata-only audit ledger records by default: an audit trail enabled only after an incident cannot explain the incident, and the rows are strictly less sensitive than the transcripts every install already stores. audit.enabled=false stops new writes at the gateway subscription seam; audit.list and openclaw audit keep serving existing records until they expire. Documented in the configuration reference, protocol page, and CLI reference. * fix: repair full-matrix CI findings after rebase - break the dynamic-tools/dynamic-tool-execution import cycle by extracting resolveCodexToolAbortTerminalReason into a leaf module - restore main's session-worktree protocol exports lost in the index.ts auto-merge - register the audit event writer worker as a knip entry point - docs table formatting; subagent wait-cancellation test scoped to its audit intent (outcome + timing) and advanced past main's new lifecycle-timeout retry grace
90 lines
2.8 KiB
TypeScript
90 lines
2.8 KiB
TypeScript
/**
|
|
* Trusted diagnostics emitted around Codex dynamic tool execution lifecycle.
|
|
*/
|
|
import { emitTrustedDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
import type { CodexDynamicToolCallParams, CodexDynamicToolCallResponse } from "./protocol.js";
|
|
|
|
type DynamicToolDiagnosticContext = {
|
|
call: CodexDynamicToolCallParams;
|
|
agentId?: string | undefined;
|
|
runId?: string | undefined;
|
|
sessionId?: string | undefined;
|
|
sessionKey?: string | undefined;
|
|
};
|
|
|
|
/** Emits a start event for one Codex dynamic tool call. */
|
|
export function emitDynamicToolStartedDiagnostic(params: DynamicToolDiagnosticContext): void {
|
|
emitTrustedDiagnosticEvent({
|
|
type: "tool.execution.started",
|
|
agentId: params.agentId,
|
|
runId: params.runId,
|
|
sessionId: params.sessionId,
|
|
sessionKey: params.sessionKey,
|
|
toolName: params.call.tool,
|
|
toolCallId: params.call.callId,
|
|
});
|
|
}
|
|
|
|
/** Emits an error event for one Codex dynamic tool call. */
|
|
export function emitDynamicToolErrorDiagnostic(
|
|
params: DynamicToolDiagnosticContext & {
|
|
durationMs: number;
|
|
terminalReason?: "failed" | "cancelled" | "timed_out";
|
|
},
|
|
): void {
|
|
emitTrustedDiagnosticEvent({
|
|
type: "tool.execution.error",
|
|
agentId: params.agentId,
|
|
runId: params.runId,
|
|
sessionId: params.sessionId,
|
|
sessionKey: params.sessionKey,
|
|
toolName: params.call.tool,
|
|
toolCallId: params.call.callId,
|
|
durationMs: params.durationMs,
|
|
errorCategory: "codex_dynamic_tool_error",
|
|
terminalReason: params.terminalReason ?? "failed",
|
|
});
|
|
}
|
|
|
|
/** Emits the terminal event matching a dynamic tool response's diagnostic type. */
|
|
export function emitDynamicToolTerminalDiagnostic(
|
|
params: DynamicToolDiagnosticContext & {
|
|
response: CodexDynamicToolCallResponse;
|
|
durationMs: number;
|
|
},
|
|
): void {
|
|
const terminalType =
|
|
params.response.diagnosticTerminalType ?? (params.response.success ? "completed" : "error");
|
|
if (terminalType === "completed") {
|
|
emitTrustedDiagnosticEvent({
|
|
type: "tool.execution.completed",
|
|
agentId: params.agentId,
|
|
runId: params.runId,
|
|
sessionId: params.sessionId,
|
|
sessionKey: params.sessionKey,
|
|
toolName: params.call.tool,
|
|
toolCallId: params.call.callId,
|
|
durationMs: params.durationMs,
|
|
});
|
|
return;
|
|
}
|
|
if (terminalType === "blocked") {
|
|
emitTrustedDiagnosticEvent({
|
|
type: "tool.execution.blocked",
|
|
agentId: params.agentId,
|
|
runId: params.runId,
|
|
sessionId: params.sessionId,
|
|
sessionKey: params.sessionKey,
|
|
toolName: params.call.tool,
|
|
toolCallId: params.call.callId,
|
|
deniedReason: "plugin-before-tool-call",
|
|
reason: "Tool call blocked",
|
|
});
|
|
return;
|
|
}
|
|
emitDynamicToolErrorDiagnostic({
|
|
...params,
|
|
terminalReason: params.response.diagnosticTerminalReason ?? "failed",
|
|
});
|
|
}
|