Files
openclaw/extensions/codex/src/app-server/dynamic-tool-diagnostics.ts
T
Peter Steinberger f53346944d feat: correlate native search outcomes in audit history (#98704)
* 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
2026-07-06 12:30:12 +01:00

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",
});
}