Files
Jyotisha/frontend/src/lib/consultation-budget.ts
T

64 lines
1.7 KiB
TypeScript

export const CONSULTATION_TOTAL_BUDGET_MS = 110_000;
export const CONSULTATION_INTERPRET_RESERVE_MS = 20_000;
export const CONSULTATION_ANSWER_RESERVE_MS = 45_000;
export type ConsultationBudgetStage = "tool" | "interpret" | "compose";
export type ConsultationBudgetGrant = Readonly<{
stage: ConsultationBudgetStage;
requestedMs: number;
grantedMs: number;
remainingMs: number;
degraded: boolean;
}>;
export type ConsultationBudget = {
readonly totalMs: number;
usedMs: number;
take(stage: ConsultationBudgetStage, requestedMs: number): ConsultationBudgetGrant;
remainingMs(): number;
abortSignal(grantedMs: number): AbortSignal;
};
export function createConsultationBudget(
totalMs = CONSULTATION_TOTAL_BUDGET_MS,
): ConsultationBudget {
let usedMs = 0;
return {
totalMs,
get usedMs() {
return usedMs;
},
set usedMs(value: number) {
usedMs = Math.max(0, value);
},
remainingMs() {
return Math.max(0, totalMs - usedMs);
},
take(stage, requestedMs) {
const remainingMs = Math.max(0, totalMs - usedMs);
const grantedMs = Math.max(0, Math.min(requestedMs, remainingMs));
return {
stage,
requestedMs,
grantedMs,
remainingMs: remainingMs - grantedMs,
degraded: grantedMs < requestedMs,
};
},
abortSignal(grantedMs) {
return AbortSignal.timeout(Math.max(1, grantedMs));
},
};
}
export function logTruncatedReasoning(requestId: string, text: string): void {
const trimmed = text.trim();
if (!trimmed) return;
console.info("[consult-reasoning]", {
requestId,
length: trimmed.length,
head: trimmed.slice(0, 80),
});
}