mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
feat(settings): set how hard the Coach thinks, cap it as an operator, edit its memory
Thinking depth (Off, Low, Medium, High) sits under the model in the Coach's quick settings and in Settings → Coach. It renders the resolved block from the account payload: levels above the operator's cap are disabled and say so, the field locks with one sentence when the operator switched reasoning off, and Off reads Minimal where the provider cannot stop thinking. The provider's own reasoning select leaves the quick settings and says the Coach has its own. The operator gets a switch to allow deeper thinking and a select for the highest depth. The memory list shows where each entry came from, lets it be edited in place, and is linked from the quick settings with its count. The deep-linked data section no longer draws a ring.
This commit is contained in:
1 parent
11bafd68b5
commit
c95dcb34db
14 files changed
+726
-143
No files matched your search
@@ -15,6 +15,8 @@ vi.mock("@/hooks/use-ai-capability", () => ({
|
||||
reason: coachState.available ? null : "no_provider",
|
||||
onDeviceAllowed: false,
|
||||
}),
|
||||
// v1.41 — the thinking depth reads the resolved block; none here.
|
||||
useCoachReasoning: () => null,
|
||||
}));
|
||||
vi.mock("next/navigation", () => ({
|
||||
useRouter: () => ({ push: vi.fn(), replace: vi.fn() }),
|
||||
|
||||
@@ -25,10 +25,17 @@ import { CoachMemorySection } from "../coach-memory-section";
|
||||
|
||||
interface SeedFact {
|
||||
id: string;
|
||||
category: "preference" | "condition" | "goal" | "constraint" | "context";
|
||||
category:
|
||||
| "preference"
|
||||
| "condition"
|
||||
| "goal"
|
||||
| "constraint"
|
||||
| "context"
|
||||
| "medication";
|
||||
text: string;
|
||||
confidence: number;
|
||||
createdAt: string;
|
||||
source?: "user" | "coach" | "extracted" | "pattern";
|
||||
}
|
||||
|
||||
const NOW = "2026-06-04T12:00:00.000Z";
|
||||
@@ -152,4 +159,45 @@ describe("Settings — CoachMemorySection", () => {
|
||||
expect(withFacts).toContain("rolling summary");
|
||||
expect(empty).toContain("rolling summary");
|
||||
});
|
||||
|
||||
it("says where each fact came from, and offers to edit it", () => {
|
||||
const html = render([
|
||||
{ ...buildFacts()[0], source: "user" },
|
||||
{ ...buildFacts()[1], source: "coach" },
|
||||
{ ...buildFacts()[2], source: "extracted" },
|
||||
{
|
||||
id: "fact-med-1",
|
||||
category: "medication",
|
||||
text: "Takes ramipril in the morning",
|
||||
confidence: 1,
|
||||
createdAt: NOW,
|
||||
source: "user",
|
||||
},
|
||||
]);
|
||||
expect(
|
||||
html.match(/data-slot="settings-coach-memory-source"/g),
|
||||
).toHaveLength(4);
|
||||
expect(html).toContain("from you");
|
||||
expect(html).toContain("from the Coach");
|
||||
expect(html.match(/data-slot="settings-coach-memory-edit"/g)).toHaveLength(
|
||||
4,
|
||||
);
|
||||
expect(html).toMatch(
|
||||
/data-slot="settings-coach-memory-edit"[^>]*aria-label="Edit"/,
|
||||
);
|
||||
// Medications get their own group.
|
||||
expect(html).toContain(
|
||||
'data-testid="settings-coach-memory-group-medication"',
|
||||
);
|
||||
expect(html).toContain("Medications");
|
||||
// The quick settings land here.
|
||||
expect(html).toMatch(/<section[^>]*id="coach-memory"/);
|
||||
});
|
||||
|
||||
it("lists goals first", () => {
|
||||
const html = render(buildFacts());
|
||||
expect(html.indexOf("group-goal")).toBeLessThan(
|
||||
html.indexOf("group-preference"),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -13,6 +13,8 @@ vi.mock("@/hooks/use-ai-capability", () => ({
|
||||
reason: null,
|
||||
onDeviceAllowed: false,
|
||||
}),
|
||||
// v1.41 — the thinking depth reads the resolved block; none here.
|
||||
useCoachReasoning: () => null,
|
||||
}));
|
||||
vi.mock("next/navigation", () => ({
|
||||
useRouter: () => ({ push: vi.fn(), replace: vi.fn() }),
|
||||
|
||||
@@ -36,6 +36,8 @@ vi.mock("@/hooks/use-ai-capability", () => ({
|
||||
reason: null,
|
||||
onDeviceAllowed: true,
|
||||
}),
|
||||
// v1.41 — the thinking depth reads the resolved block; none here.
|
||||
useCoachReasoning: () => null,
|
||||
}));
|
||||
|
||||
const authState: {
|
||||
|
||||
Reference in new issue
Block a user