mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 22:50:51 +00:00
feat(ai): send a per-entry reasoning effort to Local and gateway providers
Reasoning models on Ollama and similar servers think by default and can spend the whole max_tokens budget before the visible answer starts, so the call comes back empty or times out. The Local and OpenAI-compatible chain entries now carry an optional reasoning setting: Default sends nothing, Off sends reasoning_effort "none", Low / Medium / High send their own value. It is stored on the entry in aiProviderChain, so a chain can mix a thinking model with one that does not know the field. - Every exported resolver binds the entry's value onto the client, the connection test included, keyed on the instance type so the operator provider, OpenAI, Anthropic and Codex never carry it. - PATCH /api/user/ai-provider accepts localReasoningEffort and compatReasoningEffort and GET reports them. A provider absent from the chain holds its value on a disabled entry; restating Default on a chain that was never customised writes nothing. - PUT /api/insights/provider-chain accepts reasoningEffort on local and openai-compatible entries, refuses it on any other, and keeps the stored value when the body leaves it out. Its schema is now shared with the OpenAPI registry. - A Default request body is byte-identical to the one sent before. Refs #1126
This commit is contained in:
1 parent
808b2672cd
commit
befac59576
18 files changed
+1350
-84
No files matched your search
@@ -18,7 +18,7 @@ import {
|
||||
SPARKLINE_MAX_POINTS,
|
||||
} from "@/lib/insights/derived/types";
|
||||
import { ANALYTICS_RANGES } from "@/lib/analytics/range-delta";
|
||||
import { PROVIDER_CHAIN_TYPES } from "@/lib/ai/provider-chain";
|
||||
import { providerChainPutSchema } from "@/lib/validations/ai-provider";
|
||||
import { PERIOD_DAYS } from "@/lib/insights/narrative/period-narrative";
|
||||
import { aiCapabilityState } from "../profile";
|
||||
|
||||
@@ -2531,36 +2531,11 @@ export const providerChainResponse = z
|
||||
"The account's AI-provider chain as the settings surface reads it. Provider TYPES and boolean state only — no key, token or account id is ever on this wire.",
|
||||
});
|
||||
|
||||
export const providerChainPutRequest = z
|
||||
.object({
|
||||
chain: z
|
||||
.array(
|
||||
z.object({
|
||||
providerType: z
|
||||
.enum(PROVIDER_CHAIN_TYPES as unknown as [string, ...string[]])
|
||||
.describe(
|
||||
"Closed allow-list. The mock provider is excluded from it structurally, which is what keeps production from reaching one.",
|
||||
),
|
||||
priority: z
|
||||
.number()
|
||||
.int()
|
||||
.optional()
|
||||
.describe(
|
||||
"ACCEPTED AND IGNORED. Priority is recomputed from the array's insertion order, so a stale client cannot persist a chain whose displayed order disagrees with its stored one. Send the order you want as the order of the array.",
|
||||
),
|
||||
enabled: z.boolean(),
|
||||
}),
|
||||
)
|
||||
.min(1)
|
||||
.describe(
|
||||
"The whole chain, in the order it should be walked. At least one entry and at most one per known provider type; a repeated type is refused.",
|
||||
),
|
||||
})
|
||||
.meta({
|
||||
id: "ProviderChainPutRequest",
|
||||
description:
|
||||
"Replaces the account's provider chain wholesale. No credential is written or read here — only which provider types exist, in what order, and which are enabled.",
|
||||
});
|
||||
export const providerChainPutRequest = providerChainPutSchema.meta({
|
||||
id: "ProviderChainPutRequest",
|
||||
description:
|
||||
"Replaces the account's provider chain wholesale. No credential is written or read here — only which provider types exist, in what order, which are enabled, and the reasoning setting of the Local and OpenAI-compatible entries.",
|
||||
});
|
||||
|
||||
// ── Read-only advisor + generation (`/api/insights/generate`) ─────────
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
} from "@/lib/validations/user-prefs";
|
||||
import {
|
||||
aiProviderPatchSchema,
|
||||
reasoningEffortSchema,
|
||||
aiTestOverrideSchema,
|
||||
} from "@/lib/validations/ai-provider";
|
||||
import {
|
||||
@@ -674,6 +675,12 @@ const aiProviderResponse = z
|
||||
.describe(
|
||||
"v1.22 (#89) — per-user response timeout for AI generation, in seconds (10–600). Null = the built-in comprehensive-briefing default (~120 s). Mainly for slow local/self-hosted backends.",
|
||||
),
|
||||
localReasoningEffort: reasoningEffortSchema.describe(
|
||||
"#1126 — reasoning setting of the Local provider entry, sent as `reasoning_effort` (`none` = Off). Null = Default: the key is not sent.",
|
||||
),
|
||||
compatReasoningEffort: reasoningEffortSchema.describe(
|
||||
"#1126 — the same for the OpenAI-compatible gateway entry.",
|
||||
),
|
||||
// v1.38.19 — the setup flow's last screen used to promise
|
||||
// that insights "work for you right away" as soon as `managedBy` read
|
||||
// `server`. That is a presence read; it never knew whether the key
|
||||
|
||||
Reference in new issue
Block a user