feat: make the conversation kill controls settable from the dashboard

The `conversations` section was only reachable by editing config.yaml, which
production ignores: config is database-backed and the YAML is imported once,
when the database has not yet been seeded. `AdvancedConfigSchema` is also a
strict object, so a PUT carrying the section was rejected outright.

- Add `conversations` to the advanced config schema and payload, so it appears
  in the dashboard's advanced JSON editor and survives a save.
- Apply the edited section field by field rather than replacing the objects,
  and read the flags through to the live config from the account runtime, so a
  save applies to a running account without a restart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Jamie BruntonandClaude Opus 5 committed 2026-08-10 12:57:56 +01:00
1 parent 4404ae75ff
commit 0a4e0064f2
4 files changed
+148 -7

No files matched your search

+22
View File
@@ -327,6 +327,28 @@ describe('conversation automation', () => {
expect(chat.sendChatMessage).toHaveBeenCalledOnce();
});
it('re-reads the screening options on every reply so a config change applies without a restart', async () => {
const screener = {
screenConversationReply: vi.fn().mockResolvedValue({
classification: 'seller', confidence: 0.95, evidence: 'selling',
}),
};
const screening = { enabled: false, killConfidence: 0.8, flagConfidence: 0.6 };
const { service, getSaved } = harness([], [], 0, { mode: 'r4r', maxAutomatedTurns: 5 }, undefined, undefined, {
screener,
screening,
});
expect((await service.processConversation(incoming(1)))?.kind).toBe('sent');
expect(screener.screenConversationReply).not.toHaveBeenCalled();
screening.enabled = true;
expect((await service.processConversation(incoming(2)))?.kind).toBe('killed');
expect(screener.screenConversationReply).toHaveBeenCalledOnce();
expect(getSaved()?.automation.status).toBe('killed');
});
it('does not call the screener at all when screening is disabled', async () => {
const screener = { screenConversationReply: vi.fn() };
const { service } = harness([], [], 0, undefined, undefined, undefined, {