mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-13 04:14:56 +00:00
fix(discord): honor disabled group history limit (#1406)
Co-authored-by: Collective Developer <man@collective.dev>
This commit is contained in:
1 parent
2b7bfec504
commit
e9898be505
9 files changed
+102
-11
No files matched your search
@@ -61,11 +61,6 @@ func New(cfg config.DiscordConfig, msgBus *bus.MessageBus, pairingSvc store.Pair
|
||||
requireMention = *cfg.RequireMention
|
||||
}
|
||||
|
||||
historyLimit := cfg.HistoryLimit
|
||||
if historyLimit == 0 {
|
||||
historyLimit = channels.DefaultGroupHistoryLimit
|
||||
}
|
||||
|
||||
ch := &Channel{
|
||||
BaseChannel: base,
|
||||
session: session,
|
||||
@@ -77,7 +72,7 @@ func New(cfg config.DiscordConfig, msgBus *bus.MessageBus, pairingSvc store.Pair
|
||||
ch.SetRequireMention(requireMention)
|
||||
ch.SetPairingService(pairingSvc)
|
||||
ch.SetGroupHistory(channels.MakeHistory(channels.TypeDiscord, pendingStore, base.TenantID()))
|
||||
ch.SetHistoryLimit(historyLimit)
|
||||
ch.SetHistoryLimit(cfg.HistoryLimit)
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package discord
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/nextlevelbuilder/goclaw/internal/channels"
|
||||
"github.com/nextlevelbuilder/goclaw/internal/config"
|
||||
)
|
||||
|
||||
func TestNewPreservesExplicitZeroHistoryLimit(t *testing.T) {
|
||||
ch, err := New(config.DiscordConfig{Token: "token", HistoryLimit: 0}, nil, nil, nil, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("New returned error: %v", err)
|
||||
}
|
||||
if got := ch.HistoryLimit(); got != 0 {
|
||||
t.Fatalf("HistoryLimit() = %d, want 0", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFactoryDefaultsMissingHistoryLimitButPreservesExplicitZero(t *testing.T) {
|
||||
creds := json.RawMessage(`{"token":"token"}`)
|
||||
|
||||
defaulted, err := Factory("discord-main", creds, json.RawMessage(`{}`), nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Factory default config returned error: %v", err)
|
||||
}
|
||||
defaultedDiscord, ok := defaulted.(*Channel)
|
||||
if !ok {
|
||||
t.Fatalf("Factory returned %T, want *discord.Channel", defaulted)
|
||||
}
|
||||
if got := defaultedDiscord.HistoryLimit(); got != channels.DefaultGroupHistoryLimit {
|
||||
t.Fatalf("default HistoryLimit() = %d, want %d", got, channels.DefaultGroupHistoryLimit)
|
||||
}
|
||||
|
||||
disabled, err := Factory("discord-disabled", creds, json.RawMessage(`{"history_limit":0}`), nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Factory explicit zero returned error: %v", err)
|
||||
}
|
||||
disabledDiscord, ok := disabled.(*Channel)
|
||||
if !ok {
|
||||
t.Fatalf("Factory returned %T, want *discord.Channel", disabled)
|
||||
}
|
||||
if got := disabledDiscord.HistoryLimit(); got != 0 {
|
||||
t.Fatalf("explicit zero HistoryLimit() = %d, want 0", got)
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ type discordInstanceConfig struct {
|
||||
GroupPolicy string `json:"group_policy,omitempty"`
|
||||
AllowFrom []string `json:"allow_from,omitempty"`
|
||||
RequireMention *bool `json:"require_mention,omitempty"`
|
||||
HistoryLimit int `json:"history_limit,omitempty"`
|
||||
HistoryLimit *int `json:"history_limit,omitempty"`
|
||||
BlockReply *bool `json:"block_reply,omitempty"`
|
||||
ChatBehavior *config.ChatBehaviorConfig `json:"chat_behavior,omitempty"`
|
||||
MediaMaxBytes int64 `json:"media_max_bytes,omitempty"`
|
||||
@@ -81,7 +81,7 @@ func buildChannel(name string, creds json.RawMessage, cfg json.RawMessage,
|
||||
DMPolicy: ic.DMPolicy,
|
||||
GroupPolicy: ic.GroupPolicy,
|
||||
RequireMention: ic.RequireMention,
|
||||
HistoryLimit: ic.HistoryLimit,
|
||||
HistoryLimit: resolveHistoryLimit(ic.HistoryLimit),
|
||||
BlockReply: ic.BlockReply,
|
||||
ChatBehavior: ic.ChatBehavior,
|
||||
MediaMaxBytes: ic.MediaMaxBytes,
|
||||
@@ -105,3 +105,10 @@ func buildChannel(name string, creds json.RawMessage, cfg json.RawMessage,
|
||||
ch.SetName(name)
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
func resolveHistoryLimit(limit *int) int {
|
||||
if limit == nil {
|
||||
return channels.DefaultGroupHistoryLimit
|
||||
}
|
||||
return *limit
|
||||
}
|
||||
@@ -152,7 +152,7 @@ type DiscordConfig struct {
|
||||
DMPolicy string `json:"dm_policy,omitempty"` // "open" (default), "allowlist", "disabled"
|
||||
GroupPolicy string `json:"group_policy,omitempty"` // "open" (default), "allowlist", "disabled"
|
||||
RequireMention *bool `json:"require_mention,omitempty"` // require @bot mention in groups (default true)
|
||||
HistoryLimit int `json:"history_limit,omitempty"` // max pending group messages for context (default 50, 0=disabled)
|
||||
HistoryLimit int `json:"history_limit,omitempty"` // max pending group messages for context (default 200, 0=disabled)
|
||||
BlockReply *bool `json:"block_reply,omitempty"` // override gateway block_reply (nil = inherit)
|
||||
ChatBehavior *ChatBehaviorConfig `json:"chat_behavior,omitempty"` // override gateway chat behavior (nil = inherit)
|
||||
MediaMaxBytes int64 `json:"media_max_bytes,omitempty"` // max media download size (default 25MB)
|
||||
|
||||
@@ -97,6 +97,9 @@ func Default() *Config {
|
||||
Telegram: TelegramConfig{
|
||||
ReactionLevel: "full",
|
||||
},
|
||||
Discord: DiscordConfig{
|
||||
HistoryLimit: 200,
|
||||
},
|
||||
},
|
||||
Gateway: GatewayConfig{
|
||||
Host: "0.0.0.0",
|
||||
|
||||
@@ -40,6 +40,9 @@ func TestDefault_SensibleDefaults(t *testing.T) {
|
||||
if cfg.Skills.SlashCommands.EffectivePrefix() != "/" {
|
||||
t.Fatalf("slash command prefix = %q, want /", cfg.Skills.SlashCommands.EffectivePrefix())
|
||||
}
|
||||
if cfg.Channels.Discord.HistoryLimit != 200 {
|
||||
t.Fatalf("default discord history limit: got %d, want 200", cfg.Channels.Discord.HistoryLimit)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,6 +56,9 @@ func TestLoad_MissingFile_UsesDefaults(t *testing.T) {
|
||||
if cfg.Gateway.Port != 18790 {
|
||||
t.Fatalf("expected default port, got %d", cfg.Gateway.Port)
|
||||
}
|
||||
if cfg.Channels.Discord.HistoryLimit != 200 {
|
||||
t.Fatalf("expected default discord history limit, got %d", cfg.Channels.Discord.HistoryLimit)
|
||||
}
|
||||
}
|
||||
|
||||
// --- Load with valid JSON5 ---
|
||||
@@ -87,6 +93,28 @@ func TestLoad_ValidJSON5(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoad_DiscordHistoryLimitExplicitZeroDisables(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
cfgPath := filepath.Join(dir, "config.json5")
|
||||
|
||||
content := `{
|
||||
"channels": {
|
||||
"discord": {
|
||||
"history_limit": 0,
|
||||
},
|
||||
},
|
||||
}`
|
||||
os.WriteFile(cfgPath, []byte(content), 0644)
|
||||
|
||||
cfg, err := Load(cfgPath)
|
||||
if err != nil {
|
||||
t.Fatalf("load error: %v", err)
|
||||
}
|
||||
if cfg.Channels.Discord.HistoryLimit != 0 {
|
||||
t.Fatalf("discord history_limit explicit zero: got %d, want 0", cfg.Channels.Discord.HistoryLimit)
|
||||
}
|
||||
}
|
||||
|
||||
// --- Load with invalid JSON5 → error ---
|
||||
|
||||
func TestLoad_InvalidJSON5(t *testing.T) {
|
||||
|
||||
@@ -84,7 +84,7 @@ export const configSchema: Record<string, FieldDef[]> = {
|
||||
{ key: 'dm_policy', label: 'DM Policy', type: 'select', options: dmPolicyOptions, defaultValue: 'pairing' },
|
||||
{ key: 'group_policy', label: 'Group Policy', type: 'select', options: groupPolicyOptions, defaultValue: 'pairing' },
|
||||
{ key: 'require_mention', label: 'Require @mention in groups', type: 'boolean', defaultValue: true },
|
||||
{ key: 'history_limit', label: 'Group History Limit', type: 'number', defaultValue: 50, help: 'Max pending group messages for context (0 = disabled)' },
|
||||
{ key: 'history_limit', label: 'Group History Limit', type: 'number', defaultValue: 200, help: 'Max pending group messages for context (0 = disabled)' },
|
||||
{ key: 'allow_from', label: 'Allowed Users', type: 'tags', help: 'Discord user IDs' },
|
||||
{ key: 'block_reply', label: 'Block Reply', type: 'select', options: blockReplyOptions, defaultValue: 'inherit', help: 'Deliver intermediate text during tool iterations' },
|
||||
],
|
||||
|
||||
@@ -73,6 +73,17 @@ describe("telegram configSchema", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("discord configSchema", () => {
|
||||
const discordConfig = configSchema["discord"]!;
|
||||
|
||||
it("matches the backend pending group history default", () => {
|
||||
const historyLimit = discordConfig.find((field) => field.key === "history_limit");
|
||||
expect(historyLimit).toBeDefined();
|
||||
expect(historyLimit!.defaultValue).toBe(200);
|
||||
expect(historyLimit!.help).toMatch(/0 = disabled/i);
|
||||
});
|
||||
});
|
||||
|
||||
describe("pancake configSchema", () => {
|
||||
const pancakeConfig = configSchema["pancake"]!;
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ export const configSchema: Record<string, FieldDef[]> = {
|
||||
{ key: "dm_policy", label: "DM Policy", type: "select", options: dmPolicyOptions, defaultValue: "pairing" },
|
||||
{ key: "group_policy", label: "Group Policy", type: "select", options: groupPolicyOptions, defaultValue: "pairing" },
|
||||
{ key: "require_mention", label: "Require @mention in groups", type: "boolean", defaultValue: true },
|
||||
{ key: "history_limit", label: "Group History Limit", type: "number", defaultValue: 50, help: "Max pending group messages for context (0 = disabled)" },
|
||||
{ key: "history_limit", label: "Group History Limit", type: "number", defaultValue: 200, help: "Max pending group messages for context (0 = disabled)" },
|
||||
{ key: "allow_from", label: "Allowed Users", type: "tags", help: "Discord user IDs" },
|
||||
...chatBehaviorOverrideFields,
|
||||
],
|
||||
|
||||
Reference in new issue
Block a user