feat(FN-4191): complete Step 4 — add chat room settings controls

Fusion-Task-Id: FN-4191
Fusion-Task-Lineage: 00fddcfc-e136-41a5-84b1-b6f53b1692cb
This commit is contained in:
Fusion
2026-05-14 04:49:42 -07:00
committed by gsxdsm
parent ca269dbc76
commit 9b97f7f023
2 changed files with 75 additions and 0 deletions

View File

@@ -2037,6 +2037,52 @@ export function SettingsModal({
</label>
<small>Show the floating chat button in the dashboard. Chat is still accessible from the Chat tab in the mobile navigation.</small>
</div>
<h4 className="settings-section-heading settings-section-heading--spaced">Chat Rooms</h4>
<div className="form-group">
<label htmlFor="chatRoomRecentVerbatimMessages">Recent verbatim room messages</label>
<input
id="chatRoomRecentVerbatimMessages"
type="number"
min="1"
className="input"
placeholder="12"
value={form.chatRoomRecentVerbatimMessages ?? ""}
onChange={(e) =>
setForm((f) => ({ ...f, chatRoomRecentVerbatimMessages: Number(e.target.value) || undefined }))
}
/>
<small>Number of most-recent chat-room messages kept verbatim in the responder transcript. Older messages are compacted into a summary block. Default: 12.</small>
</div>
<div className="form-group">
<label htmlFor="chatRoomCompactionFetchLimit">Room compaction fetch limit</label>
<input
id="chatRoomCompactionFetchLimit"
type="number"
min="1"
className="input"
placeholder="80"
value={form.chatRoomCompactionFetchLimit ?? ""}
onChange={(e) =>
setForm((f) => ({ ...f, chatRoomCompactionFetchLimit: Number(e.target.value) || undefined }))
}
/>
<small>Upper bound on messages fetched from the room store for compaction consideration. Default: 80.</small>
</div>
<div className="form-group">
<label htmlFor="chatRoomSummaryMaxChars">Room summary max characters</label>
<input
id="chatRoomSummaryMaxChars"
type="number"
min="200"
className="input"
placeholder="1500"
value={form.chatRoomSummaryMaxChars ?? ""}
onChange={(e) =>
setForm((f) => ({ ...f, chatRoomSummaryMaxChars: Number(e.target.value) || undefined }))
}
/>
<small>Hard cap on the synthesized "Earlier room context" summary block. Default: 1500.</small>
</div>
<h4 className="settings-section-heading settings-section-heading--spaced">Capacity Risk Banner</h4>
<div className="form-group">
<label htmlFor="capacityRiskBannerEnabled" className="checkbox-label">

View File

@@ -824,6 +824,35 @@ describe("SettingsModal", () => {
expect(ephemeralToggle.checked).toBe(true);
});
it("renders and saves chat room compaction controls", async () => {
renderModal({ initialSection: "general" });
await waitForSettingsModalReady();
expect(screen.getByRole("heading", { name: "Chat Rooms" })).toBeInTheDocument();
const recentInput = screen.getByLabelText("Recent verbatim room messages") as HTMLInputElement;
const fetchLimitInput = screen.getByLabelText("Room compaction fetch limit") as HTMLInputElement;
const summaryMaxInput = screen.getByLabelText("Room summary max characters") as HTMLInputElement;
expect(recentInput.placeholder).toBe("12");
expect(fetchLimitInput.placeholder).toBe("80");
expect(summaryMaxInput.placeholder).toBe("1500");
await userEvent.type(recentInput, "7");
await userEvent.type(fetchLimitInput, "60");
await userEvent.type(summaryMaxInput, "900");
await userEvent.click(screen.getByRole("button", { name: "Save" }));
await waitFor(() => {
expect(mockUpdateSettings).toHaveBeenCalled();
});
const payload = mockUpdateSettings.mock.calls[0][0] as Record<string, unknown>;
expect(payload.chatRoomRecentVerbatimMessages).toBe(7);
expect(payload.chatRoomCompactionFetchLimit).toBe(60);
expect(payload.chatRoomSummaryMaxChars).toBe(900);
});
it("renders and saves GitHub tracking controls in the General section", async () => {
renderModal({ initialSection: "general" });
await waitForSettingsModalReady();