mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-05 01:31:36 +00:00
* 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
40 lines
1.7 KiB
TypeScript
40 lines
1.7 KiB
TypeScript
/** Return true for the normalized liveness state that means a run is blocked. */
|
|
export function isBlockedLivenessState(livenessState: unknown): boolean {
|
|
return typeof livenessState === "string" && livenessState.trim().toLowerCase() === "blocked";
|
|
}
|
|
|
|
/** Return true for the normalized liveness state that means a run ended incomplete. */
|
|
export function isAbandonedLivenessState(livenessState: unknown): boolean {
|
|
return typeof livenessState === "string" && livenessState.trim().toLowerCase() === "abandoned";
|
|
}
|
|
|
|
/** Convert a blocked-run error payload into a user-facing wait/status message. */
|
|
export function formatBlockedLivenessError(error: unknown): string {
|
|
const message = typeof error === "string" ? error.trim() : "";
|
|
return message || "Agent run blocked before producing a usable result.";
|
|
}
|
|
|
|
/** Convert an abandoned-run error payload into a user-facing wait/status message. */
|
|
export function formatAbandonedLivenessError(error: unknown): string {
|
|
const message = typeof error === "string" ? error.trim() : "";
|
|
return message || "Agent run ended before producing a complete result.";
|
|
}
|
|
|
|
/** Coerce any blocked liveness state into an error status while preserving other statuses. */
|
|
export function normalizeBlockedLivenessWaitStatus<
|
|
TStatus extends "ok" | "error" | "timeout" | "pending",
|
|
>(params: {
|
|
status: TStatus;
|
|
livenessState?: unknown;
|
|
error?: unknown;
|
|
}): { status: TStatus | "error"; error?: string } {
|
|
const error = typeof params.error === "string" ? params.error : undefined;
|
|
if (!isBlockedLivenessState(params.livenessState)) {
|
|
return { status: params.status, error };
|
|
}
|
|
return {
|
|
status: "error",
|
|
error: formatBlockedLivenessError(error),
|
|
};
|
|
}
|