refactor(ai): keep one name for one completion's ceiling

A status run is one completion, so its ceiling was the completion ceiling
under a second name. The Local client also re-exported a JSON-mode helper
nobody imported from it.
This commit is contained in:
Marc-André Bombeck committed 2026-10-25 04:50:25 +01:00
1 parent 8fee138256
commit 240a135b88
7 files changed
+14 -22

No files matched your search

+4 -5
View File
@@ -55,7 +55,6 @@ import { QUEUE_RUNTIME, type QueueRuntime } from "@/lib/jobs/queue-runtime";
import {
COMPLETION_CEILING_MS,
COMPREHENSIVE_WARM_CEILING_MS,
STATUS_RUN_CEILING_MS,
} from "@/lib/jobs/model-time";
import {
COMPREHENSIVE_MODEL_CALLS,
@@ -147,7 +146,7 @@ function modelSecondsOf(runs: {
completions?: number;
}) {
return (
((runs.status ?? 0) * STATUS_RUN_CEILING_MS +
((runs.status ?? 0) * COMPLETION_CEILING_MS +
(runs.comprehensive ?? 0) * COMPREHENSIVE_WARM_CEILING_MS +
(runs.completions ?? 0) * COMPLETION_CEILING_MS) /
1000
@@ -204,7 +203,7 @@ describe("jobs that wait on the response timeout outlast it", () => {
});
it("sizes the run ceilings from the largest setting and the call counts", () => {
expect(STATUS_RUN_CEILING_MS).toBe(
expect(COMPLETION_CEILING_MS).toBe(
AI_RESPONSE_TIMEOUT_MAX_SECONDS * 1000 * STATUS_MODEL_CALLS,
);
expect(COMPREHENSIVE_WARM_CEILING_MS).toBeGreaterThan(
@@ -238,14 +237,14 @@ describe("jobs that wait on the response timeout outlast it", () => {
},
"coach-memory-refresh": {
runtime: "bounded",
modelSeconds: STATUS_RUN_CEILING_MS / 1000,
modelSeconds: COMPLETION_CEILING_MS / 1000,
expireInSeconds: 1400,
expiryVia: [],
why: "planted: one run counted instead of three",
},
};
expect(findings(before)).toEqual([
`coach-memory-refresh: model time ${STATUS_RUN_CEILING_MS / 1000}s below the ${modelSecondsOf({ status: 3 })}s its runs take`,
`coach-memory-refresh: model time ${COMPLETION_CEILING_MS / 1000}s below the ${modelSecondsOf({ status: 3 })}s its runs take`,
"morning-digest-refresh: declared short, but it waits on the person's response timeout",
]);
});
+2 -2
View File
@@ -22,7 +22,7 @@
import { getGlobalBoss } from "@/lib/jobs/boss-instance";
import { annotate } from "@/lib/logging/context";
import {
STATUS_RUN_CEILING_MS,
COMPLETION_CEILING_MS,
expireAboveModelTime,
} from "@/lib/jobs/model-time";
@@ -41,7 +41,7 @@ export const COACH_MEMORY_MODEL_RUNS = 3;
* beside the refresh still writing (#1274).
*/
export const COACH_MEMORY_REFRESH_EXPIRE_SECONDS = expireAboveModelTime(
COACH_MEMORY_MODEL_RUNS * STATUS_RUN_CEILING_MS,
COACH_MEMORY_MODEL_RUNS * COMPLETION_CEILING_MS,
);
/** How long a conversation must be quiet before its memory is refreshed. */
-3
View File
@@ -12,7 +12,6 @@ import {
} from "./openai-wire";
import {
hasLearnedJsonModeDialect,
isResponseFormatRejection,
jsonModeDialectFor,
rememberJsonModeDialect,
resetJsonModeDialectCache,
@@ -66,8 +65,6 @@ type LocalJsonDialect = JsonModeDialect;
/** Test hook — clears the learned per-endpoint dialect cache. */
export const resetLocalJsonDialectCache = resetJsonModeDialectCache;
export { isResponseFormatRejection };
/**
* #89 — the streaming path's absolute backstop. The real ceiling is the
* per-idle-gap timer; this only stops a server that streams forever.
@@ -4,7 +4,7 @@
* worker registry and every sender can read them without loading it.
*/
import {
STATUS_RUN_CEILING_MS,
COMPLETION_CEILING_MS,
expireAboveModelTime,
} from "@/lib/jobs/model-time";
@@ -17,7 +17,7 @@ export const INSIGHT_STATUS_GENERATE_QUEUE = "insight-status-generate";
* retry beside the generation still running (#1274).
*/
export const INSIGHT_STATUS_GENERATE_EXPIRE_SECONDS = expireAboveModelTime(
STATUS_RUN_CEILING_MS,
COMPLETION_CEILING_MS,
);
/**
+1 -4
View File
@@ -63,14 +63,11 @@ export function comprehensiveWarmBudgetMs(
* it: the call and the one repeat the Local and gateway clients send when a
* thinking model answered with reasoning alone (`STATUS_MODEL_CALLS`), each
* at the full timeout. A document read's call and its corrective retry are
* two completions.
* two completions; a status run (`runStatusCompletion`) is one.
*/
export const COMPLETION_CEILING_MS =
AI_RESPONSE_TIMEOUT_MAX_MS * STATUS_MODEL_CALLS;
/** The longest one status run (`runStatusCompletion`, one completion) waits. */
export const STATUS_RUN_CEILING_MS = COMPLETION_CEILING_MS;
/**
* Room a job's expiry leaves on top of its model work for what the handler
* does around it: reading the record, building the prompt, persisting.
+3 -4
View File
@@ -61,7 +61,6 @@ import {
import {
COMPLETION_CEILING_MS,
COMPREHENSIVE_WARM_CEILING_MS,
STATUS_RUN_CEILING_MS,
} from "@/lib/jobs/model-time";
import { DOCUMENT_INDEX_EXPIRE_SECONDS } from "@/lib/jobs/document-index-queue";
import { DOCUMENT_SUMMARY_EXPIRE_SECONDS } from "@/lib/jobs/document-summary-queue";
@@ -199,7 +198,7 @@ export const QUEUE_RUNTIME: Readonly<Record<string, QueueRuntime>> = {
},
"insight-status-generate": {
runtime: "bounded",
modelSeconds: STATUS_RUN_CEILING_MS / 1000,
modelSeconds: COMPLETION_CEILING_MS / 1000,
expireInSeconds: INSIGHT_STATUS_GENERATE_EXPIRE_SECONDS,
expiryVia: ["INSIGHT_STATUS_GENERATE_EXPIRE_SECONDS"],
why: "One account, one note: one status run, the call and its one reasoning repeat at the account's timeout.",
@@ -208,7 +207,7 @@ export const QUEUE_RUNTIME: Readonly<Record<string, QueueRuntime>> = {
"reaction-line-generate": short("One provider call for one reaction line."),
"workout-insight-generate": {
runtime: "bounded",
modelSeconds: STATUS_RUN_CEILING_MS / 1000,
modelSeconds: COMPLETION_CEILING_MS / 1000,
expireInSeconds: WORKOUT_INSIGHT_GENERATE_EXPIRE_SECONDS,
expiryVia: ["WORKOUT_INSIGHT_GENERATE_EXPIRE_SECONDS"],
why: "One workout's line: one status run at the account's timeout.",
@@ -235,7 +234,7 @@ export const QUEUE_RUNTIME: Readonly<Record<string, QueueRuntime>> = {
},
"coach-memory-refresh": {
runtime: "bounded",
modelSeconds: (COACH_MEMORY_MODEL_RUNS * STATUS_RUN_CEILING_MS) / 1000,
modelSeconds: (COACH_MEMORY_MODEL_RUNS * COMPLETION_CEILING_MS) / 1000,
expireInSeconds: COACH_MEMORY_REFRESH_EXPIRE_SECONDS,
expiryVia: ["COACH_MEMORY_REFRESH_EXPIRE_SECONDS"],
why: "One conversation's summary, facts and plan proposals: three status runs in a row at the account's timeout.",
@@ -16,7 +16,7 @@ import { getGlobalBoss } from "@/lib/jobs/boss-instance";
import { annotate } from "@/lib/logging/context";
import { logCaught } from "@/lib/logging/signal";
import {
STATUS_RUN_CEILING_MS,
COMPLETION_CEILING_MS,
expireAboveModelTime,
} from "@/lib/jobs/model-time";
@@ -30,7 +30,7 @@ export const WORKOUT_INSIGHT_GENERATE_QUEUE = "workout-insight-generate";
* the attempt was recorded as a failure.
*/
export const WORKOUT_INSIGHT_GENERATE_EXPIRE_SECONDS = expireAboveModelTime(
STATUS_RUN_CEILING_MS,
COMPLETION_CEILING_MS,
);
/** Serial — this is a provider path, kept off the request pool entirely. */