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:
@@ -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">
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user