import { type EnvironmentId, OrchestrationGetFullThreadDiffInput, OrchestrationGetTurnDiffInput, ThreadId,} from "@t3tools/contracts";import { queryOptions } from "@tanstack/react-query";import { Option, Schema } from "effect";import { ensureEnvironmentApi } from "../environmentApi"; interface CheckpointDiffQueryInput { environmentId: EnvironmentId | null; threadId: ThreadId | null; fromTurnCount: number | null; toTurnCount: number | null; ignoreWhitespace: boolean; cacheScope?: string | null; enabled?: boolean;} export const providerQueryKeys = { all: ["providers"] as const, checkpointDiff: (input: CheckpointDiffQueryInput) => [ "providers", "checkpointDiff", input.environmentId ?? null, input.threadId, input.fromTurnCount, input.toTurnCount, input.ignoreWhitespace, input.cacheScope ?? null, ] as const,}; function decodeCheckpointDiffRequest(input: CheckpointDiffQueryInput) { if (input.fromTurnCount === 0) { return Schema.decodeUnknownOption(OrchestrationGetFullThreadDiffInput)({ threadId: input.threadId, toTurnCount: input.toTurnCount, ignoreWhitespace: input.ignoreWhitespace, }).pipe(Option.map((fields) => ({ kind: "fullThreadDiff" as const, input: fields }))); } return Schema.decodeUnknownOption(OrchestrationGetTurnDiffInput)({ threadId: input.threadId, fromTurnCount: input.fromTurnCount, toTurnCount: input.toTurnCount, ignoreWhitespace: input.ignoreWhitespace, }).pipe(Option.map((fields) => ({ kind: "turnDiff" as const, input: fields })));} function asCheckpointErrorMessage(error: unknown): string { if (error instanceof Error) { return error.message; } if (typeof error === "string") { return error; } return "";} function normalizeCheckpointErrorMessage(error: unknown): string { const message = asCheckpointErrorMessage(error).trim(); if (message.length === 0) { return "Failed to load checkpoint diff."; } const lower = message.toLowerCase(); if (lower.includes("not a git repository")) { return "Turn diffs are unavailable because this project is not a git repository."; } if ( lower.includes("checkpoint unavailable for thread") || lower.includes("checkpoint invariant violation") ) { const separatorIndex = message.indexOf(":"); if (separatorIndex >= 0) { const detail = message.slice(separatorIndex + 1).trim(); if (detail.length > 0) { return detail; } } } return message;} function isCheckpointTemporarilyUnavailable(error: unknown): boolean { const message = asCheckpointErrorMessage(error).toLowerCase(); return ( message.includes("exceeds current turn count") || message.includes("checkpoint is unavailable for turn") || message.includes("filesystem checkpoint is unavailable") );} export function checkpointDiffQueryOptions(input: CheckpointDiffQueryInput) { const decodedRequest = decodeCheckpointDiffRequest(input); return queryOptions({ queryKey: providerQueryKeys.checkpointDiff(input), queryFn: async () => { if (!input.environmentId || !input.threadId || decodedRequest._tag === "None") { throw new Error("Checkpoint diff is unavailable."); } const api = ensureEnvironmentApi(input.environmentId); try { if (decodedRequest.value.kind === "fullThreadDiff") { return await api.orchestration.getFullThreadDiff(decodedRequest.value.input); } return await api.orchestration.getTurnDiff(decodedRequest.value.input); } catch (error) { throw new Error(normalizeCheckpointErrorMessage(error), { cause: error }); } }, enabled: (input.enabled ?? true) && !!input.environmentId && !!input.threadId && decodedRequest._tag === "Some", staleTime: Infinity, retry: (failureCount, error) => { if (isCheckpointTemporarilyUnavailable(error)) { return failureCount < 12; } return failureCount < 3; }, retryDelay: (attempt, error) => isCheckpointTemporarilyUnavailable(error) ? Math.min(5_000, 250 * 2 ** (attempt - 1)) : Math.min(1_000, 100 * 2 ** (attempt - 1)), });}
import {
type EnvironmentId,
OrchestrationGetFullThreadDiffInput,
OrchestrationGetTurnDiffInput,
ThreadId,
} from "@t3tools/contracts";
import { queryOptions } from "@tanstack/react-query";
import { Option, Schema } from "effect";
import { ensureEnvironmentApi } from "../environmentApi";
interface CheckpointDiffQueryInput {
environmentId: EnvironmentId | null;
threadId: ThreadId | null;
fromTurnCount: number | null;
toTurnCount: number | null;
ignoreWhitespace: boolean;
cacheScope?: string | null;
enabled?: boolean;
}
export const providerQueryKeys = {
all: ["providers"] as const,
checkpointDiff: (input: CheckpointDiffQueryInput) =>
[
"providers",
"checkpointDiff",
input.environmentId ?? null,
input.threadId,
input.fromTurnCount,
input.toTurnCount,
input.ignoreWhitespace,
input.cacheScope ?? null,
] as const,
};
function decodeCheckpointDiffRequest(input: CheckpointDiffQueryInput) {
if (input.fromTurnCount === 0) {
return Schema.decodeUnknownOption(OrchestrationGetFullThreadDiffInput)({
threadId: input.threadId,
toTurnCount: input.toTurnCount,
ignoreWhitespace: input.ignoreWhitespace,
}).pipe(Option.map((fields) => ({ kind: "fullThreadDiff" as const, input: fields })));
}
return Schema.decodeUnknownOption(OrchestrationGetTurnDiffInput)({
threadId: input.threadId,
fromTurnCount: input.fromTurnCount,
toTurnCount: input.toTurnCount,
ignoreWhitespace: input.ignoreWhitespace,
}).pipe(Option.map((fields) => ({ kind: "turnDiff" as const, input: fields })));
}
function asCheckpointErrorMessage(error: unknown): string {
if (error instanceof Error) {
return error.message;
}
if (typeof error === "string") {
return error;
}
return "";
}
function normalizeCheckpointErrorMessage(error: unknown): string {
const message = asCheckpointErrorMessage(error).trim();
if (message.length === 0) {
return "Failed to load checkpoint diff.";
}
const lower = message.toLowerCase();
if (lower.includes("not a git repository")) {
return "Turn diffs are unavailable because this project is not a git repository.";
}
if (
lower.includes("checkpoint unavailable for thread") ||
lower.includes("checkpoint invariant violation")
) {
const separatorIndex = message.indexOf(":");
if (separatorIndex >= 0) {
const detail = message.slice(separatorIndex + 1).trim();
if (detail.length > 0) {
return detail;
}
}
}
return message;
}
function isCheckpointTemporarilyUnavailable(error: unknown): boolean {
const message = asCheckpointErrorMessage(error).toLowerCase();
return (
message.includes("exceeds current turn count") ||
message.includes("checkpoint is unavailable for turn") ||
message.includes("filesystem checkpoint is unavailable")
);
}
export function checkpointDiffQueryOptions(input: CheckpointDiffQueryInput) {
const decodedRequest = decodeCheckpointDiffRequest(input);
return queryOptions({
queryKey: providerQueryKeys.checkpointDiff(input),
queryFn: async () => {
if (!input.environmentId || !input.threadId || decodedRequest._tag === "None") {
throw new Error("Checkpoint diff is unavailable.");
}
const api = ensureEnvironmentApi(input.environmentId);
try {
if (decodedRequest.value.kind === "fullThreadDiff") {
return await api.orchestration.getFullThreadDiff(decodedRequest.value.input);
}
return await api.orchestration.getTurnDiff(decodedRequest.value.input);
} catch (error) {
throw new Error(normalizeCheckpointErrorMessage(error), { cause: error });
}
},
enabled:
(input.enabled ?? true) &&
!!input.environmentId &&
!!input.threadId &&
decodedRequest._tag === "Some",
staleTime: Infinity,
retry: (failureCount, error) => {
if (isCheckpointTemporarilyUnavailable(error)) {
return failureCount < 12;
}
return failureCount < 3;
},
retryDelay: (attempt, error) =>
isCheckpointTemporarilyUnavailable(error)
? Math.min(5_000, 250 * 2 ** (attempt - 1))
: Math.min(1_000, 100 * 2 ** (attempt - 1)),
});
}