mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 22:26:13 +00:00
The daily briefing and the per-metric status assessments ignored the per-user response-timeout setting: they hardcoded their per-surface AI_BUDGETS default, so raising the timeout for a slow self-hosted or local backend had no effect and the surfaces still aborted early. Only the coach threaded the setting through. Resolve the effective timeout from User.aiResponseTimeoutSeconds in one shared helper and thread it onto every non-coach generation call: - runStatusCompletion is the single chokepoint every status / reference surface funnels through (per-metric cards, the batched assessment, the derived assessments, the period narratives), so resolving it there applies the setting to all of them at once — on both the upstream call's own timeout and the outer wall-clock cap that previously clipped a raised value at 60 s. - The comprehensive briefing generator and the user-initiated regenerate route thread it onto the main generation, the JSON retry, the grounding retry, and the paragraph re-roll. On a failed generation the briefing keeps its last good text — no cache row is written, so the previous payload stays intact — and records a dated, append-only failure marker (no migration; reuses the audit-log JSON pattern). The read path compares the marker against the last successful generation so it can tell a held briefing from a current one.
27 lines
1023 B
TypeScript
27 lines
1023 B
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { resolveEffectiveTimeoutMs } from "../effective-timeout";
|
|
|
|
const BUDGET = 120_000;
|
|
|
|
describe("resolveEffectiveTimeoutMs", () => {
|
|
it("converts a positive per-user setting from seconds to ms", () => {
|
|
expect(resolveEffectiveTimeoutMs(300, BUDGET)).toBe(300_000);
|
|
expect(resolveEffectiveTimeoutMs(10, BUDGET)).toBe(10_000);
|
|
});
|
|
|
|
it("falls back to the budget default when the setting is unset", () => {
|
|
expect(resolveEffectiveTimeoutMs(null, BUDGET)).toBe(BUDGET);
|
|
expect(resolveEffectiveTimeoutMs(undefined, BUDGET)).toBe(BUDGET);
|
|
});
|
|
|
|
it("falls back to the budget default for a non-positive value", () => {
|
|
expect(resolveEffectiveTimeoutMs(0, BUDGET)).toBe(BUDGET);
|
|
expect(resolveEffectiveTimeoutMs(-5, BUDGET)).toBe(BUDGET);
|
|
});
|
|
|
|
it("honours different budget defaults per surface", () => {
|
|
expect(resolveEffectiveTimeoutMs(null, 60_000)).toBe(60_000);
|
|
expect(resolveEffectiveTimeoutMs(45, 60_000)).toBe(45_000);
|
|
});
|
|
});
|