feat: persist settings and enrich conversation context
This commit is contained in:
1 parent
a36723a325
commit
2c100d72b6
84 files changed
+2248
-644
No files matched your search
+59
-10
@@ -1,11 +1,36 @@
|
||||
import { Router } from 'express';
|
||||
import type { WebContext } from '../context.js';
|
||||
import { SubredditConfigSchema, type SubredditConfig } from '../../config/index.js';
|
||||
import { ConfigSchema, SubredditConfigSchema, type SubredditConfig } from '../../config/index.js';
|
||||
import { TONE_KEYS } from '../../config/tone-profiles.js';
|
||||
import { persistSubreddits } from '../../config/persistence.js';
|
||||
import { z } from 'zod';
|
||||
|
||||
const SubredditsUpdateSchema = z.array(SubredditConfigSchema).min(1);
|
||||
const AdvancedConfigSchema = z.strictObject({
|
||||
reddit: ConfigSchema.shape.reddit.omit({
|
||||
subreddits: true,
|
||||
prioritizeRecentPosts: true,
|
||||
recentWindowMinutes: true,
|
||||
}),
|
||||
openrouter: ConfigSchema.shape.openrouter.omit({ apiKey: true }),
|
||||
browser: z.strictObject({ sessionDir: z.string() }),
|
||||
media: ConfigSchema.shape.media,
|
||||
strategies: ConfigSchema.shape.strategies,
|
||||
chatStrategies: ConfigSchema.shape.chatStrategies,
|
||||
});
|
||||
|
||||
function advancedConfig(ctx: WebContext): z.infer<typeof AdvancedConfigSchema> {
|
||||
const { subreddits: _subreddits, prioritizeRecentPosts: _prioritize, recentWindowMinutes: _window, ...reddit } = ctx.config.reddit;
|
||||
const { apiKey: _apiKey, ...openrouter } = ctx.config.openrouter;
|
||||
const { dryRun: _dryRun, ...browser } = ctx.config.browser;
|
||||
return {
|
||||
reddit,
|
||||
openrouter,
|
||||
browser,
|
||||
media: ctx.config.media,
|
||||
strategies: ctx.config.strategies,
|
||||
chatStrategies: ctx.config.chatStrategies,
|
||||
};
|
||||
}
|
||||
|
||||
export function createConfigRouter(ctx: WebContext): Router {
|
||||
const router = Router();
|
||||
@@ -17,12 +42,30 @@ export function createConfigRouter(ctx: WebContext): Router {
|
||||
reddit: ctx.runtimeConfig.reddit,
|
||||
subreddits: ctx.config.reddit.subreddits,
|
||||
tones: TONE_KEYS,
|
||||
advanced: advancedConfig(ctx),
|
||||
});
|
||||
});
|
||||
|
||||
router.put('/config', (req, res) => {
|
||||
try {
|
||||
const updates = req.body;
|
||||
const configStore = ctx.services.configStore;
|
||||
if (!configStore) throw new Error('Configuration persistence is unavailable');
|
||||
|
||||
const parsedSubreddits = updates.subreddits === undefined
|
||||
? null
|
||||
: SubredditsUpdateSchema.safeParse(updates.subreddits);
|
||||
if (parsedSubreddits && !parsedSubreddits.success) {
|
||||
res.status(400).json({ error: 'Invalid subreddits payload', detail: parsedSubreddits.error.format() });
|
||||
return;
|
||||
}
|
||||
const parsedAdvanced = updates.advanced === undefined
|
||||
? null
|
||||
: AdvancedConfigSchema.safeParse(updates.advanced);
|
||||
if (parsedAdvanced && !parsedAdvanced.success) {
|
||||
res.status(400).json({ error: 'Invalid advanced configuration', detail: parsedAdvanced.error.format() });
|
||||
return;
|
||||
}
|
||||
|
||||
if (updates.rateLimit) {
|
||||
if (typeof updates.rateLimit.minDelayBetweenMessagesMs === 'number') {
|
||||
@@ -65,13 +108,8 @@ export function createConfigRouter(ctx: WebContext): Router {
|
||||
ctx.config.reddit.prioritizeRecentPosts = ctx.runtimeConfig.reddit.prioritizeRecentPosts;
|
||||
ctx.config.reddit.recentWindowMinutes = ctx.runtimeConfig.reddit.recentWindowMinutes;
|
||||
|
||||
if (updates.subreddits !== undefined) {
|
||||
const parsed = SubredditsUpdateSchema.safeParse(updates.subreddits);
|
||||
if (!parsed.success) {
|
||||
res.status(400).json({ error: 'Invalid subreddits payload', detail: parsed.error.format() });
|
||||
return;
|
||||
}
|
||||
const next: SubredditConfig[] = parsed.data;
|
||||
if (parsedSubreddits?.success) {
|
||||
const next: SubredditConfig[] = parsedSubreddits.data;
|
||||
const seen = new Set<string>();
|
||||
for (const s of next) {
|
||||
const key = s.name.toLowerCase();
|
||||
@@ -81,10 +119,20 @@ export function createConfigRouter(ctx: WebContext): Router {
|
||||
}
|
||||
seen.add(key);
|
||||
}
|
||||
persistSubreddits(next);
|
||||
ctx.config.reddit.subreddits = next;
|
||||
}
|
||||
|
||||
if (parsedAdvanced?.success) {
|
||||
Object.assign(ctx.config.reddit, parsedAdvanced.data.reddit);
|
||||
Object.assign(ctx.config.openrouter, parsedAdvanced.data.openrouter);
|
||||
Object.assign(ctx.config.browser, parsedAdvanced.data.browser);
|
||||
ctx.config.media = parsedAdvanced.data.media;
|
||||
ctx.config.strategies = parsedAdvanced.data.strategies;
|
||||
ctx.config.chatStrategies = parsedAdvanced.data.chatStrategies;
|
||||
}
|
||||
|
||||
configStore.save(ctx.config);
|
||||
|
||||
ctx.getOnConfigChange()?.(ctx.runtimeConfig);
|
||||
|
||||
ctx.activity.push('info', 'Config updated via dashboard');
|
||||
@@ -94,6 +142,7 @@ export function createConfigRouter(ctx: WebContext): Router {
|
||||
success: true,
|
||||
config: ctx.runtimeConfig,
|
||||
subreddits: ctx.config.reddit.subreddits,
|
||||
advanced: advancedConfig(ctx),
|
||||
});
|
||||
} catch (error) {
|
||||
ctx.logger.error('Failed to update config:', error);
|
||||
|
||||
Reference in new issue
Block a user