From ebb7d5b24f8df42b15d1a412ec0a9f73f2c7c2d2 Mon Sep 17 00:00:00 2001 From: Pip Build Date: Wed, 25 Feb 2026 23:53:32 -0500 Subject: [PATCH 01/10] feat: add starboard, permissions, memory, and rate limit config sections to web dashboard --- .../components/dashboard/config-editor.tsx | 407 +++++++++++++++++- web/src/types/config.ts | 49 ++- 2 files changed, 444 insertions(+), 12 deletions(-) diff --git a/web/src/components/dashboard/config-editor.tsx b/web/src/components/dashboard/config-editor.tsx index ce511e37..0ecd586b 100644 --- a/web/src/components/dashboard/config-editor.tsx +++ b/web/src/components/dashboard/config-editor.tsx @@ -38,7 +38,7 @@ const inputClasses = function isGuildConfig(data: unknown): data is GuildConfig { if (typeof data !== "object" || data === null || Array.isArray(data)) return false; const obj = data as Record; - const knownSections = ["ai", "welcome", "spam", "moderation", "triage"] as const; + const knownSections = ["ai", "welcome", "spam", "moderation", "triage", "starboard", "permissions", "memory"] as const; const hasKnownSection = knownSections.some((key) => key in obj); if (!hasKnownSection) return false; for (const key of knownSections) { @@ -316,42 +316,42 @@ export function ConfigEditor() { const updateSystemPrompt = useCallback((value: string) => { setDraftConfig((prev) => { if (!prev) return prev; - return { ...prev, ai: { ...prev.ai, systemPrompt: value } }; + return { ...prev, ai: { ...prev.ai, systemPrompt: value } } as GuildConfig; }); }, []); const updateAiEnabled = useCallback((enabled: boolean) => { setDraftConfig((prev) => { if (!prev) return prev; - return { ...prev, ai: { ...prev.ai, enabled } }; + return { ...prev, ai: { ...prev.ai, enabled } } as GuildConfig; }); }, []); const updateWelcomeEnabled = useCallback((enabled: boolean) => { setDraftConfig((prev) => { if (!prev) return prev; - return { ...prev, welcome: { ...prev.welcome, enabled } }; + return { ...prev, welcome: { ...prev.welcome, enabled } } as GuildConfig; }); }, []); const updateWelcomeMessage = useCallback((message: string) => { setDraftConfig((prev) => { if (!prev) return prev; - return { ...prev, welcome: { ...prev.welcome, message } }; + return { ...prev, welcome: { ...prev.welcome, message } } as GuildConfig; }); }, []); const updateModerationEnabled = useCallback((enabled: boolean) => { setDraftConfig((prev) => { if (!prev) return prev; - return { ...prev, moderation: { ...prev.moderation, enabled } }; + return { ...prev, moderation: { ...prev.moderation, enabled } } as GuildConfig; }); }, []); const updateModerationField = useCallback((field: string, value: unknown) => { setDraftConfig((prev) => { if (!prev) return prev; - return { ...prev, moderation: { ...prev.moderation, [field]: value } }; + return { ...prev, moderation: { ...prev.moderation, [field]: value } } as GuildConfig; }); }, []); @@ -364,7 +364,7 @@ export function ConfigEditor() { ...prev.moderation, dmNotifications: { ...prev.moderation?.dmNotifications, [action]: value }, }, - }; + } as GuildConfig; }); }, []); @@ -377,21 +377,68 @@ export function ConfigEditor() { ...prev.moderation, escalation: { ...prev.moderation?.escalation, enabled }, }, - }; + } as GuildConfig; }); }, []); const updateTriageEnabled = useCallback((enabled: boolean) => { setDraftConfig((prev) => { if (!prev) return prev; - return { ...prev, triage: { ...prev.triage, enabled } }; + return { ...prev, triage: { ...prev.triage, enabled } } as GuildConfig; }); }, []); const updateTriageField = useCallback((field: string, value: unknown) => { setDraftConfig((prev) => { if (!prev) return prev; - return { ...prev, triage: { ...prev.triage, [field]: value } }; + return { ...prev, triage: { ...prev.triage, [field]: value } } as GuildConfig; + }); + }, []); + + const updateStarboardField = useCallback((field: string, value: unknown) => { + setDraftConfig((prev) => { + if (!prev) return prev; + return { ...prev, starboard: { ...prev.starboard, [field]: value } } as GuildConfig; + }); + }, []); + + const updateRateLimitField = useCallback((field: string, value: unknown) => { + setDraftConfig((prev) => { + if (!prev) return prev; + return { + ...prev, + moderation: { + ...prev.moderation, + rateLimit: { ...prev.moderation?.rateLimit, [field]: value }, + }, + } as GuildConfig; + }); + }, []); + + const updateLinkFilterField = useCallback((field: string, value: unknown) => { + setDraftConfig((prev) => { + if (!prev) return prev; + return { + ...prev, + moderation: { + ...prev.moderation, + linkFilter: { ...prev.moderation?.linkFilter, [field]: value }, + }, + } as GuildConfig; + }); + }, []); + + const updatePermissionsField = useCallback((field: string, value: unknown) => { + setDraftConfig((prev) => { + if (!prev) return prev; + return { ...prev, permissions: { ...prev.permissions, [field]: value } } as GuildConfig; + }); + }, []); + + const updateMemoryField = useCallback((field: string, value: unknown) => { + setDraftConfig((prev) => { + if (!prev) return prev; + return { ...prev, memory: { ...prev.memory, [field]: value } } as GuildConfig; }); }, []); @@ -617,6 +664,139 @@ export function ConfigEditor() { label="Escalation" /> + + {/* Rate Limiting sub-section */} +
+ Rate Limiting +
+ Enabled + updateRateLimitField("enabled", v)} + disabled={saving} + label="Rate Limiting" + /> +
+
+ + +
+
+ + + +
+
+ + {/* Link Filtering sub-section */} +
+ Link Filtering +
+ Enabled + updateLinkFilterField("enabled", v)} + disabled={saving} + label="Link Filtering" + /> +
+ +
)} @@ -800,6 +980,15 @@ export function ConfigEditor() { label="Debug Footer" /> +
+ Status Reactions + updateTriageField("statusReactions", v)} + disabled={saving} + label="Status Reactions" + /> +
From 143cc51aa18540387da2d3f9f69aaec96ae0ead5 Mon Sep 17 00:00:00 2001 From: Pip Build Date: Thu, 26 Feb 2026 14:13:23 -0500 Subject: [PATCH 05/10] feat: default starboard emoji to '*' in web config --- web/src/components/dashboard/config-editor.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/components/dashboard/config-editor.tsx b/web/src/components/dashboard/config-editor.tsx index 4aa63eb0..1683d38d 100644 --- a/web/src/components/dashboard/config-editor.tsx +++ b/web/src/components/dashboard/config-editor.tsx @@ -1031,11 +1031,11 @@ export function ConfigEditor() {
updateStarboardField("emoji", e.target.value.trim() || "⭐")} + value={draftConfig.starboard?.emoji ?? "*"} + onChange={(e) => updateStarboardField("emoji", e.target.value.trim() || "*")} disabled={saving} className={inputClasses} - placeholder="⭐" + placeholder="*" />