Files
horus-3d/src/features/agents/operations/historyLifecycleWorkflow.ts
T
Luke The Dev 4fa4f13558 First Release of Claw3D (#11)
Co-authored-by: iamlukethedev <iamlukethedev@users.noreply.github.com>
2026-03-19 23:14:04 -05:00

120 lines
3.3 KiB
TypeScript

import type { AgentState } from "@/features/agents/state/store";
export type HistoryRequestIntent =
| {
kind: "skip";
reason: "missing-agent" | "session-not-created" | "missing-session-key" | "in-flight";
}
| {
kind: "fetch";
sessionKey: string;
limit: number;
requestRevision: number;
requestEpoch: number;
requestId: string;
loadedAt: number;
};
export type HistoryResponseDisposition =
| {
kind: "drop";
reason:
| "session-key-changed"
| "session-epoch-changed"
| "transcript-revision-changed";
}
| {
kind: "apply";
};
const resolveHistoryFetchLimit = (params: {
requestedLimit?: number;
defaultLimit: number;
maxLimit: number;
}): number => {
const requested = params.requestedLimit;
if (typeof requested !== "number" || !Number.isFinite(requested) || requested <= 0) {
return params.defaultLimit;
}
return Math.min(params.maxLimit, Math.floor(requested));
};
export const resolveHistoryRequestIntent = (params: {
agent: AgentState | null;
requestedLimit?: number;
maxLimit: number;
defaultLimit: number;
inFlightSessionKeys: Set<string>;
requestId: string;
loadedAt: number;
}): HistoryRequestIntent => {
if (!params.agent) {
return { kind: "skip", reason: "missing-agent" };
}
if (!params.agent.sessionCreated) {
return { kind: "skip", reason: "session-not-created" };
}
const sessionKey = params.agent.sessionKey.trim();
if (!sessionKey) {
return { kind: "skip", reason: "missing-session-key" };
}
if (params.inFlightSessionKeys.has(sessionKey)) {
return { kind: "skip", reason: "in-flight" };
}
return {
kind: "fetch",
sessionKey,
limit: resolveHistoryFetchLimit({
requestedLimit: params.requestedLimit,
defaultLimit: params.defaultLimit,
maxLimit: params.maxLimit,
}),
requestRevision: params.agent.transcriptRevision ?? params.agent.outputLines.length,
requestEpoch: params.agent.sessionEpoch ?? 0,
requestId: params.requestId,
loadedAt: params.loadedAt,
};
};
export const resolveHistoryResponseDisposition = (params: {
latestAgent: AgentState | null;
expectedSessionKey: string;
requestEpoch: number;
requestRevision: number;
}): HistoryResponseDisposition => {
const latest = params.latestAgent;
if (!latest || latest.sessionKey.trim() !== params.expectedSessionKey) {
return { kind: "drop", reason: "session-key-changed" };
}
if ((latest.sessionEpoch ?? 0) !== params.requestEpoch) {
return { kind: "drop", reason: "session-epoch-changed" };
}
const latestRevision = latest.transcriptRevision ?? latest.outputLines.length;
if (latestRevision !== params.requestRevision) {
return { kind: "drop", reason: "transcript-revision-changed" };
}
return { kind: "apply" };
};
export const buildHistoryMetadataPatch = (params: {
loadedAt: number;
fetchedCount: number;
limit: number;
requestId: string;
}): Pick<
AgentState,
| "historyLoadedAt"
| "historyFetchLimit"
| "historyFetchedCount"
| "historyMaybeTruncated"
| "lastAppliedHistoryRequestId"
> => {
return {
historyLoadedAt: params.loadedAt,
historyFetchLimit: params.limit,
historyFetchedCount: params.fetchedCount,
historyMaybeTruncated: params.fetchedCount >= params.limit,
lastAppliedHistoryRequestId: params.requestId,
};
};