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

+9
View File
@@ -14,6 +14,7 @@ const AdvancedConfigSchema = z.strictObject({
}),
openrouter: ConfigSchema.shape.openrouter.omit({ apiKey: true }),
browser: z.strictObject({ sessionDir: z.string() }),
conversations: ConfigSchema.shape.conversations,
media: ConfigSchema.shape.media,
strategies: ConfigSchema.shape.strategies,
chatStrategies: ConfigSchema.shape.chatStrategies,
@@ -33,6 +34,7 @@ function advancedConfig(ctx: WebContext): z.infer<typeof AdvancedConfigSchema> {
reddit,
openrouter,
browser,
conversations: ctx.config.conversations,
media: ctx.config.media,
strategies: ctx.config.strategies,
chatStrategies: ctx.config.chatStrategies,
@@ -140,6 +142,13 @@ export function createConfigRouter(ctx: WebContext): Router {
Object.assign(ctx.config.reddit, parsedAdvanced.data.reddit);
Object.assign(ctx.config.openrouter, parsedAdvanced.data.openrouter);
Object.assign(ctx.config.browser, parsedAdvanced.data.browser);
// Assigned field by field, never replaced: running account runtimes
// hold a reference to these objects and read the kill controls on every
// reply, so a dashboard save applies without a restart.
const nextConversations = parsedAdvanced.data.conversations;
ctx.config.conversations.offPlatformKill = nextConversations.offPlatformKill;
ctx.config.conversations.killOnSellerKeyword = nextConversations.killOnSellerKeyword;
Object.assign(ctx.config.conversations.aiReplyScreening, nextConversations.aiReplyScreening);
ctx.config.media = parsedAdvanced.data.media;
ctx.config.strategies = parsedAdvanced.data.strategies;
ctx.config.chatStrategies = parsedAdvanced.data.chatStrategies;