feat(server,contracts,web): dashboard library counts and engine runs triggeredBy/multi-status filters

- GET /dashboard: automation.library {entities, movies, series, seasons,
  episodes, assets} and automation.slotSatisfiedRate; home media overview
  shows the counts instead of placeholders.
- GET /engine/runs: `status` accepts comma-separated values; new
  `triggeredBy` filter (comma-separated) evaluated server-side by scanning
  batches and paging with the last inspected row's cursor (scan cap 2000).
- Task stream: source filter and the "active" tab (running,pending) are now
  one paginated server query.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-28 16:49:11 +08:00
1 parent 615917bb45
commit 363f85b1a1
13 files changed
+165 -250

No files matched your search

+5 -1
View File
@@ -5,7 +5,10 @@ import { qk } from "~/lib/query-keys.ts";
import { errorCode } from "./parse.ts";
export type EngineRunFilters = {
/** 单值或逗号分隔多值(running,pending) */
status?: string;
/** 触发来源,单值或逗号分隔多值(user,api_key) */
triggeredBy?: string;
workflowName?: string;
businessKind?: EngineBusinessKind;
businessRefId?: string;
@@ -16,9 +19,10 @@ export type EngineRunFilters = {
/** 终态:不能再 cancel */
export const ENGINE_TERMINAL = new Set(["completed", "succeeded", "failed", "canceled"]);
export function useEngineRuns(filters: EngineRunFilters, enabled = true) {
export function useEngineRuns(filters: EngineRunFilters, enabled = true, refetchMs: number | false = false) {
return useInfiniteQuery({
enabled,
refetchInterval: refetchMs,
queryKey: qk.list("engine", filters),
initialPageParam: undefined as string | undefined,
queryFn: ({ pageParam, signal }) =>