Files
kandev/apps/web/components/task/use-agent-error-acknowledgements.ts
T
Carlos Florêncio 1abb1c914e fix: keep acknowledged agent errors hidden (#1558)
* fix: keep acknowledged agent errors hidden

* fix: address agent error acknowledgement review

* fix: include fallback sessions in error acknowledgements

* test: cover agent error acknowledgement helpers

---------

Co-authored-by: root <root@kandev.ts.net>
2026-06-30 16:29:46 +01:00

85 lines
2.8 KiB
TypeScript

"use client";
import { useEffect } from "react";
import { useAppStore, useAppStoreApi } from "@/components/state-provider";
import {
type AgentErrorOptions,
resolvedAgentErrorAcknowledgementStamp,
} from "@/lib/task-agent-error";
import type { TaskSession } from "@/lib/types/http";
import { isTerminalSessionState } from "@/lib/ws/handlers/agent-session";
type UseAgentErrorAcknowledgementsParams = {
sessionsById: Record<string, TaskSession>;
sessionIds: readonly string[];
messagesBySession: AgentErrorOptions["messagesBySession"];
dismissedAgentErrors: Record<string, string>;
};
/**
* Mirrors the sessions `agentErrorMessageForTask` can inspect for visible task
* rows. Primary sessions are included directly; fallback sessions are included
* only while non-terminal because terminal sessions will not produce a later
* agent message that can make their error acknowledgement stale.
*/
export function agentErrorAcknowledgementSessionIds(
tasks: Array<{ id: string; primarySessionId?: string | null }>,
sessionsByTaskId: Record<string, TaskSession[] | undefined>,
): string[] {
const sessionIds = new Set<string>();
for (const task of tasks) {
if (task.primarySessionId) sessionIds.add(task.primarySessionId);
for (const session of sessionsByTaskId[task.id] ?? []) {
if (!isTerminalSessionState(session.state)) sessionIds.add(session.id);
}
}
return [...sessionIds];
}
/**
* Builds a stable content key for primary session IDs so derived arrays only
* change when their contents change. The NUL separator avoids collisions with
* commas or newlines in IDs, preventing avoidable bulk WS re-subscriptions.
*/
export function stablePrimarySessionIdsKey(
tasks: Array<{ primarySessionId?: string | null }>,
): string {
return tasks
.map((task) => task.primarySessionId)
.filter((sessionId): sessionId is string => sessionId != null)
.join("\0");
}
export function usePersistResolvedAgentErrorAcknowledgements({
sessionsById,
sessionIds,
messagesBySession,
dismissedAgentErrors,
}: UseAgentErrorAcknowledgementsParams) {
const store = useAppStoreApi();
const acknowledgeAgentErrors = useAppStore((state) => state.acknowledgeAgentErrors);
useEffect(() => {
const acknowledgedAgentErrors = store.getState().acknowledgedAgentErrors;
const stamps: Record<string, string> = {};
for (const sessionId of sessionIds) {
const session = sessionsById[sessionId];
if (!session) continue;
const stamp = resolvedAgentErrorAcknowledgementStamp(sessionId, session, {
messagesBySession,
dismissedAgentErrors,
acknowledgedAgentErrors,
});
if (stamp) stamps[sessionId] = stamp;
}
acknowledgeAgentErrors(stamps);
}, [
acknowledgeAgentErrors,
dismissedAgentErrors,
messagesBySession,
sessionIds,
sessionsById,
store,
]);
}