mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-07 07:11:06 +00:00
feat(tasks): move task ledger to sqlite and add audit CLI (#57361)
* feat(tasks): move task ledger to sqlite * feat(tasks): add task run audit command * style(tasks): normalize audit command formatting * fix(tasks): address audit summary and sqlite perms * fix(tasks): avoid duplicate lost audit findings
This commit is contained in:
@@ -7,6 +7,7 @@ const healthCommand = vi.fn();
|
||||
const sessionsCommand = vi.fn();
|
||||
const sessionsCleanupCommand = vi.fn();
|
||||
const tasksListCommand = vi.fn();
|
||||
const tasksAuditCommand = vi.fn();
|
||||
const tasksShowCommand = vi.fn();
|
||||
const tasksNotifyCommand = vi.fn();
|
||||
const tasksCancelCommand = vi.fn();
|
||||
@@ -32,6 +33,7 @@ vi.mock("../../commands/sessions-cleanup.js", () => ({
|
||||
|
||||
vi.mock("../../commands/tasks.js", () => ({
|
||||
tasksListCommand,
|
||||
tasksAuditCommand,
|
||||
tasksShowCommand,
|
||||
tasksNotifyCommand,
|
||||
tasksCancelCommand,
|
||||
@@ -67,6 +69,7 @@ describe("registerStatusHealthSessionsCommands", () => {
|
||||
sessionsCommand.mockResolvedValue(undefined);
|
||||
sessionsCleanupCommand.mockResolvedValue(undefined);
|
||||
tasksListCommand.mockResolvedValue(undefined);
|
||||
tasksAuditCommand.mockResolvedValue(undefined);
|
||||
tasksShowCommand.mockResolvedValue(undefined);
|
||||
tasksNotifyCommand.mockResolvedValue(undefined);
|
||||
tasksCancelCommand.mockResolvedValue(undefined);
|
||||
@@ -242,6 +245,30 @@ describe("registerStatusHealthSessionsCommands", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("runs tasks audit subcommand with filters", async () => {
|
||||
await runCli([
|
||||
"tasks",
|
||||
"--json",
|
||||
"audit",
|
||||
"--severity",
|
||||
"error",
|
||||
"--code",
|
||||
"stale_running",
|
||||
"--limit",
|
||||
"5",
|
||||
]);
|
||||
|
||||
expect(tasksAuditCommand).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
json: true,
|
||||
severity: "error",
|
||||
code: "stale_running",
|
||||
limit: 5,
|
||||
}),
|
||||
runtime,
|
||||
);
|
||||
});
|
||||
|
||||
it("runs tasks notify subcommand with lookup and policy forwarding", async () => {
|
||||
await runCli(["tasks", "notify", "run-123", "state_changes"]);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { sessionsCleanupCommand } from "../../commands/sessions-cleanup.js";
|
||||
import { sessionsCommand } from "../../commands/sessions.js";
|
||||
import { statusCommand } from "../../commands/status.js";
|
||||
import {
|
||||
tasksAuditCommand,
|
||||
tasksCancelCommand,
|
||||
tasksListCommand,
|
||||
tasksNotifyCommand,
|
||||
@@ -272,6 +273,38 @@ export function registerStatusHealthSessionsCommands(program: Command) {
|
||||
});
|
||||
});
|
||||
|
||||
tasksCmd
|
||||
.command("audit")
|
||||
.description("Show stale or broken background task runs")
|
||||
.option("--json", "Output as JSON", false)
|
||||
.option("--severity <level>", "Filter by severity (warn, error)")
|
||||
.option(
|
||||
"--code <name>",
|
||||
"Filter by finding code (stale_queued, stale_running, lost, delivery_failed, missing_cleanup, inconsistent_timestamps)",
|
||||
)
|
||||
.option("--limit <n>", "Limit displayed findings")
|
||||
.action(async (opts, command) => {
|
||||
const parentOpts = command.parent?.opts() as { json?: boolean } | undefined;
|
||||
await runCommandWithRuntime(defaultRuntime, async () => {
|
||||
await tasksAuditCommand(
|
||||
{
|
||||
json: Boolean(opts.json || parentOpts?.json),
|
||||
severity: opts.severity as "warn" | "error" | undefined,
|
||||
code: opts.code as
|
||||
| "stale_queued"
|
||||
| "stale_running"
|
||||
| "lost"
|
||||
| "delivery_failed"
|
||||
| "missing_cleanup"
|
||||
| "inconsistent_timestamps"
|
||||
| undefined,
|
||||
limit: parsePositiveIntOrUndefined(opts.limit),
|
||||
},
|
||||
defaultRuntime,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
tasksCmd
|
||||
.command("show")
|
||||
.description("Show one background task by task id, run id, or session key")
|
||||
|
||||
Reference in New Issue
Block a user