refactor: remove max_context_load_time and max_context_tokens from bot settings

These two fields controlled history context window (time-based) and token-based
trimming. They are no longer needed — the resolver now always uses the hardcoded
24-hour default and skips token-based history trimming.
This commit is contained in:
Acbox
2026-03-29 00:00:10 +08:00
parent 90ac222bc9
commit 0730ff2945
25 changed files with 176 additions and 388 deletions
-2
View File
@@ -808,8 +808,6 @@
"memoryHealthUnavailable": "Unavailable",
"ttsModel": "TTS Model",
"ttsModelPlaceholder": "Select TTS model",
"maxContextLoadTime": "Max Context Load Time",
"maxContextTokens": "Max Context Tokens",
"language": "Language",
"reasoningEnabled": "Enable Reasoning",
"reasoningEffort": "Reasoning Effort",
-2
View File
@@ -804,8 +804,6 @@
"memoryHealthUnavailable": "暂不可用",
"ttsModel": "语音合成模型",
"ttsModelPlaceholder": "选择语音合成模型",
"maxContextLoadTime": "最大上下文加载时间",
"maxContextTokens": "最大上下文Token数",
"language": "语言",
"reasoningEnabled": "启用推理",
"reasoningEffort": "推理等级",
@@ -199,29 +199,6 @@
<Separator />
<!-- Max Context Load Time -->
<div class="space-y-2">
<Label>{{ $t('bots.settings.maxContextLoadTime') }}</Label>
<Input
v-model.number="form.max_context_load_time"
type="number"
:min="0"
:aria-label="$t('bots.settings.maxContextLoadTime')"
/>
</div>
<!-- Max Context Tokens -->
<div class="space-y-2">
<Label>{{ $t('bots.settings.maxContextTokens') }}</Label>
<Input
v-model.number="form.max_context_tokens"
type="number"
:min="0"
placeholder="0"
:aria-label="$t('bots.settings.maxContextTokens')"
/>
</div>
<!-- Language -->
<div class="space-y-2">
<Label>{{ $t('bots.settings.language') }}</Label>
@@ -492,8 +469,6 @@ const form = reactive({
memory_provider_id: '',
tts_model_id: '',
browser_context_id: '',
max_context_load_time: 0,
max_context_tokens: 0,
language: '',
reasoning_enabled: false,
reasoning_effort: 'medium',
@@ -617,8 +592,6 @@ watch(settings, (val) => {
form.memory_provider_id = val.memory_provider_id ?? ''
form.tts_model_id = val.tts_model_id ?? ''
form.browser_context_id = val.browser_context_id ?? ''
form.max_context_load_time = val.max_context_load_time ?? 0
form.max_context_tokens = val.max_context_tokens ?? 0
form.language = val.language ?? ''
form.reasoning_enabled = val.reasoning_enabled ?? false
form.reasoning_effort = val.reasoning_effort || 'medium'
@@ -635,8 +608,6 @@ const hasChanges = computed(() => {
|| form.memory_provider_id !== (s.memory_provider_id ?? '')
|| form.tts_model_id !== (s.tts_model_id ?? '')
|| form.browser_context_id !== (s.browser_context_id ?? '')
|| form.max_context_load_time !== (s.max_context_load_time ?? 0)
|| form.max_context_tokens !== (s.max_context_tokens ?? 0)
|| form.language !== (s.language ?? '')
|| form.reasoning_enabled !== (s.reasoning_enabled ?? false)
|| form.reasoning_effort !== (s.reasoning_effort || 'medium')
-2
View File
@@ -162,8 +162,6 @@ CREATE TABLE IF NOT EXISTS bots (
timezone TEXT,
is_active BOOLEAN NOT NULL DEFAULT true,
status TEXT NOT NULL DEFAULT 'ready',
max_context_load_time INTEGER NOT NULL DEFAULT 1440,
max_context_tokens INTEGER NOT NULL DEFAULT 0,
language TEXT NOT NULL DEFAULT 'auto',
reasoning_enabled BOOLEAN NOT NULL DEFAULT false,
reasoning_effort TEXT NOT NULL DEFAULT 'medium',
@@ -0,0 +1,5 @@
-- 0051_drop_max_context_fields
-- Re-add max_context_load_time and max_context_tokens columns to bots table
ALTER TABLE bots ADD COLUMN IF NOT EXISTS max_context_load_time INTEGER NOT NULL DEFAULT 1440;
ALTER TABLE bots ADD COLUMN IF NOT EXISTS max_context_tokens INTEGER NOT NULL DEFAULT 0;
@@ -0,0 +1,5 @@
-- 0051_drop_max_context_fields
-- Remove max_context_load_time and max_context_tokens columns from bots table
ALTER TABLE bots DROP COLUMN IF EXISTS max_context_load_time;
ALTER TABLE bots DROP COLUMN IF EXISTS max_context_tokens;
+5 -5
View File
@@ -1,15 +1,15 @@
-- name: CreateBot :one
INSERT INTO bots (owner_user_id, display_name, avatar_url, timezone, is_active, metadata, status)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, max_context_load_time, max_context_tokens, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at;
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at;
-- name: GetBotByID :one
SELECT id, owner_user_id, display_name, avatar_url, timezone, is_active, status, max_context_load_time, max_context_tokens, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, compaction_enabled, compaction_threshold, compaction_model_id, metadata, created_at, updated_at
SELECT id, owner_user_id, display_name, avatar_url, timezone, is_active, status, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, compaction_enabled, compaction_threshold, compaction_model_id, metadata, created_at, updated_at
FROM bots
WHERE id = $1;
-- name: ListBotsByOwner :many
SELECT id, owner_user_id, display_name, avatar_url, timezone, is_active, status, max_context_load_time, max_context_tokens, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at
SELECT id, owner_user_id, display_name, avatar_url, timezone, is_active, status, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at
FROM bots
WHERE owner_user_id = $1
ORDER BY created_at DESC;
@@ -23,14 +23,14 @@ SET display_name = $2,
metadata = $6,
updated_at = now()
WHERE id = $1
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, max_context_load_time, max_context_tokens, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at;
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at;
-- name: UpdateBotOwner :one
UPDATE bots
SET owner_user_id = $2,
updated_at = now()
WHERE id = $1
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, max_context_load_time, max_context_tokens, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at;
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at;
-- name: UpdateBotStatus :exec
UPDATE bots
+3 -11
View File
@@ -1,8 +1,6 @@
-- name: GetSettingsByBotID :one
SELECT
bots.id AS bot_id,
bots.max_context_load_time,
bots.max_context_tokens,
bots.language,
bots.reasoning_enabled,
bots.reasoning_effort,
@@ -33,9 +31,7 @@ WHERE bots.id = $1;
-- name: UpsertBotSettings :one
WITH updated AS (
UPDATE bots
SET max_context_load_time = sqlc.arg(max_context_load_time),
max_context_tokens = sqlc.arg(max_context_tokens),
language = sqlc.arg(language),
SET language = sqlc.arg(language),
reasoning_enabled = sqlc.arg(reasoning_enabled),
reasoning_effort = sqlc.arg(reasoning_effort),
heartbeat_enabled = sqlc.arg(heartbeat_enabled),
@@ -53,12 +49,10 @@ WITH updated AS (
browser_context_id = COALESCE(sqlc.narg(browser_context_id)::uuid, bots.browser_context_id),
updated_at = now()
WHERE bots.id = sqlc.arg(id)
RETURNING bots.id, bots.max_context_load_time, bots.max_context_tokens, bots.language, bots.reasoning_enabled, bots.reasoning_effort, bots.heartbeat_enabled, bots.heartbeat_interval, bots.heartbeat_prompt, bots.compaction_enabled, bots.compaction_threshold, bots.chat_model_id, bots.heartbeat_model_id, bots.compaction_model_id, bots.title_model_id, bots.search_provider_id, bots.memory_provider_id, bots.tts_model_id, bots.browser_context_id
RETURNING bots.id, bots.language, bots.reasoning_enabled, bots.reasoning_effort, bots.heartbeat_enabled, bots.heartbeat_interval, bots.heartbeat_prompt, bots.compaction_enabled, bots.compaction_threshold, bots.chat_model_id, bots.heartbeat_model_id, bots.compaction_model_id, bots.title_model_id, bots.search_provider_id, bots.memory_provider_id, bots.tts_model_id, bots.browser_context_id
)
SELECT
updated.id AS bot_id,
updated.max_context_load_time,
updated.max_context_tokens,
updated.language,
updated.reasoning_enabled,
updated.reasoning_effort,
@@ -87,9 +81,7 @@ LEFT JOIN browser_contexts ON browser_contexts.id = updated.browser_context_id;
-- name: DeleteSettingsByBotID :exec
UPDATE bots
SET max_context_load_time = 1440,
max_context_tokens = 0,
language = 'auto',
SET language = 'auto',
reasoning_enabled = false,
reasoning_effort = 'medium',
heartbeat_enabled = false,
+16 -18
View File
@@ -93,7 +93,7 @@ func (*fakeRows) Conn() *pgx.Conn { return nil }
func makeBotRow(botID, ownerUserID pgtype.UUID) *fakeRow {
return &fakeRow{
scanFunc: func(dest ...any) error {
if len(dest) < 24 {
if len(dest) < 22 {
return pgx.ErrNoRows
}
*dest[0].(*pgtype.UUID) = botID
@@ -103,23 +103,21 @@ func makeBotRow(botID, ownerUserID pgtype.UUID) *fakeRow {
*dest[4].(*pgtype.Text) = pgtype.Text{}
*dest[5].(*bool) = true
*dest[6].(*string) = bots.BotStatusReady
*dest[7].(*int32) = 30
*dest[8].(*int32) = 0
*dest[9].(*string) = ""
*dest[10].(*bool) = false
*dest[11].(*string) = "medium"
*dest[12].(*pgtype.UUID) = pgtype.UUID{}
*dest[13].(*pgtype.UUID) = pgtype.UUID{}
*dest[14].(*pgtype.UUID) = pgtype.UUID{}
*dest[15].(*bool) = false
*dest[16].(*int32) = 30
*dest[17].(*string) = ""
*dest[18].(*bool) = false // CompactionEnabled
*dest[19].(*int32) = 100000 // CompactionThreshold
*dest[20].(*pgtype.UUID) = pgtype.UUID{} // CompactionModelID
*dest[21].(*[]byte) = []byte(`{}`)
*dest[22].(*pgtype.Timestamptz) = pgtype.Timestamptz{}
*dest[23].(*pgtype.Timestamptz) = pgtype.Timestamptz{}
*dest[7].(*string) = "" // Language
*dest[8].(*bool) = false // ReasoningEnabled
*dest[9].(*string) = "medium" // ReasoningEffort
*dest[10].(*pgtype.UUID) = pgtype.UUID{} // ChatModelID
*dest[11].(*pgtype.UUID) = pgtype.UUID{} // SearchProviderID
*dest[12].(*pgtype.UUID) = pgtype.UUID{} // MemoryProviderID
*dest[13].(*bool) = false // HeartbeatEnabled
*dest[14].(*int32) = 30 // HeartbeatInterval
*dest[15].(*string) = "" // HeartbeatPrompt
*dest[16].(*bool) = false // CompactionEnabled
*dest[17].(*int32) = 100000 // CompactionThreshold
*dest[18].(*pgtype.UUID) = pgtype.UUID{} // CompactionModelID
*dest[19].(*[]byte) = []byte(`{}`)
*dest[20].(*pgtype.Timestamptz) = pgtype.Timestamptz{}
*dest[21].(*pgtype.Timestamptz) = pgtype.Timestamptz{}
return nil
},
}
+5 -5
View File
@@ -435,15 +435,15 @@ func asSQLCBot(v any) sqlc.Bot {
case sqlc.Bot:
return r
case sqlc.CreateBotRow:
return sqlc.Bot{ID: r.ID, OwnerUserID: r.OwnerUserID, DisplayName: r.DisplayName, AvatarUrl: r.AvatarUrl, Timezone: r.Timezone, IsActive: r.IsActive, Status: r.Status, MaxContextLoadTime: r.MaxContextLoadTime, MaxContextTokens: r.MaxContextTokens, Language: r.Language, ReasoningEnabled: r.ReasoningEnabled, ReasoningEffort: r.ReasoningEffort, ChatModelID: r.ChatModelID, SearchProviderID: r.SearchProviderID, MemoryProviderID: r.MemoryProviderID, HeartbeatEnabled: r.HeartbeatEnabled, HeartbeatInterval: r.HeartbeatInterval, HeartbeatPrompt: r.HeartbeatPrompt, Metadata: r.Metadata, CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt}
return sqlc.Bot{ID: r.ID, OwnerUserID: r.OwnerUserID, DisplayName: r.DisplayName, AvatarUrl: r.AvatarUrl, Timezone: r.Timezone, IsActive: r.IsActive, Status: r.Status, Language: r.Language, ReasoningEnabled: r.ReasoningEnabled, ReasoningEffort: r.ReasoningEffort, ChatModelID: r.ChatModelID, SearchProviderID: r.SearchProviderID, MemoryProviderID: r.MemoryProviderID, HeartbeatEnabled: r.HeartbeatEnabled, HeartbeatInterval: r.HeartbeatInterval, HeartbeatPrompt: r.HeartbeatPrompt, Metadata: r.Metadata, CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt}
case sqlc.GetBotByIDRow:
return sqlc.Bot{ID: r.ID, OwnerUserID: r.OwnerUserID, DisplayName: r.DisplayName, AvatarUrl: r.AvatarUrl, Timezone: r.Timezone, IsActive: r.IsActive, Status: r.Status, MaxContextLoadTime: r.MaxContextLoadTime, MaxContextTokens: r.MaxContextTokens, Language: r.Language, ReasoningEnabled: r.ReasoningEnabled, ReasoningEffort: r.ReasoningEffort, ChatModelID: r.ChatModelID, SearchProviderID: r.SearchProviderID, MemoryProviderID: r.MemoryProviderID, HeartbeatEnabled: r.HeartbeatEnabled, HeartbeatInterval: r.HeartbeatInterval, HeartbeatPrompt: r.HeartbeatPrompt, CompactionEnabled: r.CompactionEnabled, CompactionThreshold: r.CompactionThreshold, CompactionModelID: r.CompactionModelID, Metadata: r.Metadata, CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt}
return sqlc.Bot{ID: r.ID, OwnerUserID: r.OwnerUserID, DisplayName: r.DisplayName, AvatarUrl: r.AvatarUrl, Timezone: r.Timezone, IsActive: r.IsActive, Status: r.Status, Language: r.Language, ReasoningEnabled: r.ReasoningEnabled, ReasoningEffort: r.ReasoningEffort, ChatModelID: r.ChatModelID, SearchProviderID: r.SearchProviderID, MemoryProviderID: r.MemoryProviderID, HeartbeatEnabled: r.HeartbeatEnabled, HeartbeatInterval: r.HeartbeatInterval, HeartbeatPrompt: r.HeartbeatPrompt, CompactionEnabled: r.CompactionEnabled, CompactionThreshold: r.CompactionThreshold, CompactionModelID: r.CompactionModelID, Metadata: r.Metadata, CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt}
case sqlc.ListBotsByOwnerRow:
return sqlc.Bot{ID: r.ID, OwnerUserID: r.OwnerUserID, DisplayName: r.DisplayName, AvatarUrl: r.AvatarUrl, Timezone: r.Timezone, IsActive: r.IsActive, Status: r.Status, MaxContextLoadTime: r.MaxContextLoadTime, MaxContextTokens: r.MaxContextTokens, Language: r.Language, ReasoningEnabled: r.ReasoningEnabled, ReasoningEffort: r.ReasoningEffort, ChatModelID: r.ChatModelID, SearchProviderID: r.SearchProviderID, MemoryProviderID: r.MemoryProviderID, HeartbeatEnabled: r.HeartbeatEnabled, HeartbeatInterval: r.HeartbeatInterval, HeartbeatPrompt: r.HeartbeatPrompt, Metadata: r.Metadata, CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt}
return sqlc.Bot{ID: r.ID, OwnerUserID: r.OwnerUserID, DisplayName: r.DisplayName, AvatarUrl: r.AvatarUrl, Timezone: r.Timezone, IsActive: r.IsActive, Status: r.Status, Language: r.Language, ReasoningEnabled: r.ReasoningEnabled, ReasoningEffort: r.ReasoningEffort, ChatModelID: r.ChatModelID, SearchProviderID: r.SearchProviderID, MemoryProviderID: r.MemoryProviderID, HeartbeatEnabled: r.HeartbeatEnabled, HeartbeatInterval: r.HeartbeatInterval, HeartbeatPrompt: r.HeartbeatPrompt, Metadata: r.Metadata, CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt}
case sqlc.UpdateBotProfileRow:
return sqlc.Bot{ID: r.ID, OwnerUserID: r.OwnerUserID, DisplayName: r.DisplayName, AvatarUrl: r.AvatarUrl, Timezone: r.Timezone, IsActive: r.IsActive, Status: r.Status, MaxContextLoadTime: r.MaxContextLoadTime, MaxContextTokens: r.MaxContextTokens, Language: r.Language, ReasoningEnabled: r.ReasoningEnabled, ReasoningEffort: r.ReasoningEffort, ChatModelID: r.ChatModelID, SearchProviderID: r.SearchProviderID, MemoryProviderID: r.MemoryProviderID, HeartbeatEnabled: r.HeartbeatEnabled, HeartbeatInterval: r.HeartbeatInterval, HeartbeatPrompt: r.HeartbeatPrompt, Metadata: r.Metadata, CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt}
return sqlc.Bot{ID: r.ID, OwnerUserID: r.OwnerUserID, DisplayName: r.DisplayName, AvatarUrl: r.AvatarUrl, Timezone: r.Timezone, IsActive: r.IsActive, Status: r.Status, Language: r.Language, ReasoningEnabled: r.ReasoningEnabled, ReasoningEffort: r.ReasoningEffort, ChatModelID: r.ChatModelID, SearchProviderID: r.SearchProviderID, MemoryProviderID: r.MemoryProviderID, HeartbeatEnabled: r.HeartbeatEnabled, HeartbeatInterval: r.HeartbeatInterval, HeartbeatPrompt: r.HeartbeatPrompt, Metadata: r.Metadata, CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt}
case sqlc.UpdateBotOwnerRow:
return sqlc.Bot{ID: r.ID, OwnerUserID: r.OwnerUserID, DisplayName: r.DisplayName, AvatarUrl: r.AvatarUrl, Timezone: r.Timezone, IsActive: r.IsActive, Status: r.Status, MaxContextLoadTime: r.MaxContextLoadTime, MaxContextTokens: r.MaxContextTokens, Language: r.Language, ReasoningEnabled: r.ReasoningEnabled, ReasoningEffort: r.ReasoningEffort, ChatModelID: r.ChatModelID, SearchProviderID: r.SearchProviderID, MemoryProviderID: r.MemoryProviderID, HeartbeatEnabled: r.HeartbeatEnabled, HeartbeatInterval: r.HeartbeatInterval, HeartbeatPrompt: r.HeartbeatPrompt, Metadata: r.Metadata, CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt}
return sqlc.Bot{ID: r.ID, OwnerUserID: r.OwnerUserID, DisplayName: r.DisplayName, AvatarUrl: r.AvatarUrl, Timezone: r.Timezone, IsActive: r.IsActive, Status: r.Status, Language: r.Language, ReasoningEnabled: r.ReasoningEnabled, ReasoningEffort: r.ReasoningEffort, ChatModelID: r.ChatModelID, SearchProviderID: r.SearchProviderID, MemoryProviderID: r.MemoryProviderID, HeartbeatEnabled: r.HeartbeatEnabled, HeartbeatInterval: r.HeartbeatInterval, HeartbeatPrompt: r.HeartbeatPrompt, Metadata: r.Metadata, CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt}
default:
return sqlc.Bot{}
}
+18 -20
View File
@@ -42,15 +42,15 @@ func (d *fakeDBTX) QueryRow(ctx context.Context, sql string, args ...any) pgx.Ro
// makeBotRow creates a fakeRow that populates a sqlc.GetBotByIDRow via Scan.
// Column order: id, owner_user_id, display_name, avatar_url, timezone, is_active, status,
// max_context_load_time, max_context_tokens, language,
// reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id,
// language, reasoning_enabled, reasoning_effort,
// chat_model_id, search_provider_id, memory_provider_id,
// heartbeat_enabled, heartbeat_interval, heartbeat_prompt,
// compaction_enabled, compaction_threshold, compaction_model_id,
// metadata, created_at, updated_at.
func makeBotRow(botID, ownerUserID pgtype.UUID) *fakeRow {
return &fakeRow{
scanFunc: func(dest ...any) error {
if len(dest) < 24 {
if len(dest) < 22 {
return pgx.ErrNoRows
}
*dest[0].(*pgtype.UUID) = botID
@@ -60,23 +60,21 @@ func makeBotRow(botID, ownerUserID pgtype.UUID) *fakeRow {
*dest[4].(*pgtype.Text) = pgtype.Text{}
*dest[5].(*bool) = true
*dest[6].(*string) = BotStatusReady
*dest[7].(*int32) = 30 // MaxContextLoadTime
*dest[8].(*int32) = 4096 // MaxContextTokens
*dest[9].(*string) = "en" // Language
*dest[10].(*bool) = false // ReasoningEnabled
*dest[11].(*string) = "medium" // ReasoningEffort
*dest[12].(*pgtype.UUID) = pgtype.UUID{} // ChatModelID
*dest[13].(*pgtype.UUID) = pgtype.UUID{} // SearchProviderID
*dest[14].(*pgtype.UUID) = pgtype.UUID{} // MemoryProviderID
*dest[15].(*bool) = false // HeartbeatEnabled
*dest[16].(*int32) = 30 // HeartbeatInterval
*dest[17].(*string) = "" // HeartbeatPrompt
*dest[18].(*bool) = false // CompactionEnabled
*dest[19].(*int32) = 100000 // CompactionThreshold
*dest[20].(*pgtype.UUID) = pgtype.UUID{} // CompactionModelID
*dest[21].(*[]byte) = []byte(`{}`)
*dest[22].(*pgtype.Timestamptz) = pgtype.Timestamptz{}
*dest[23].(*pgtype.Timestamptz) = pgtype.Timestamptz{}
*dest[7].(*string) = "en" // Language
*dest[8].(*bool) = false // ReasoningEnabled
*dest[9].(*string) = "medium" // ReasoningEffort
*dest[10].(*pgtype.UUID) = pgtype.UUID{} // ChatModelID
*dest[11].(*pgtype.UUID) = pgtype.UUID{} // SearchProviderID
*dest[12].(*pgtype.UUID) = pgtype.UUID{} // MemoryProviderID
*dest[13].(*bool) = false // HeartbeatEnabled
*dest[14].(*int32) = 30 // HeartbeatInterval
*dest[15].(*string) = "" // HeartbeatPrompt
*dest[16].(*bool) = false // CompactionEnabled
*dest[17].(*int32) = 100000 // CompactionThreshold
*dest[18].(*pgtype.UUID) = pgtype.UUID{} // CompactionModelID
*dest[19].(*[]byte) = []byte(`{}`)
*dest[20].(*pgtype.Timestamptz) = pgtype.Timestamptz{}
*dest[21].(*pgtype.Timestamptz) = pgtype.Timestamptz{}
return nil
},
}
-18
View File
@@ -22,8 +22,6 @@ func (h *Handler) buildSettingsGroup() *CommandGroup {
return formatKV([]kv{
{"Language", s.Language},
{"ACL Default Effect", s.AclDefaultEffect},
{"Max Context Load Time", fmt.Sprintf("%d min", s.MaxContextLoadTime)},
{"Max Context Tokens", strconv.Itoa(s.MaxContextTokens)},
{"Reasoning Enabled", boolStr(s.ReasoningEnabled)},
{"Reasoning Effort", s.ReasoningEffort},
{"Heartbeat Enabled", boolStr(s.HeartbeatEnabled)},
@@ -75,20 +73,6 @@ func (h *Handler) buildSettingsGroup() *CommandGroup {
return fmt.Sprintf("Invalid heartbeat_interval: %s", args[i]), nil
}
req.HeartbeatInterval = &val
case "--max_context_load_time":
i++
val, err := strconv.Atoi(args[i])
if err != nil {
return fmt.Sprintf("Invalid max_context_load_time: %s", args[i]), nil
}
req.MaxContextLoadTime = &val
case "--max_context_tokens":
i++
val, err := strconv.Atoi(args[i])
if err != nil {
return fmt.Sprintf("Invalid max_context_tokens: %s", args[i]), nil
}
req.MaxContextTokens = &val
case "--chat_model_id":
i++
req.ChatModelID = args[i]
@@ -118,8 +102,6 @@ func settingsUpdateUsage() string {
"- --reasoning_effort <low|medium|high>\n" +
"- --heartbeat_enabled <true|false>\n" +
"- --heartbeat_interval <minutes>\n" +
"- --max_context_load_time <minutes>\n" +
"- --max_context_tokens <count>\n" +
"- --chat_model_id <id>\n" +
"- --heartbeat_model_id <id>"
}
+3 -37
View File
@@ -153,8 +153,6 @@ func (r *Resolver) resolve(ctx context.Context, req conversation.ChatRequest) (r
return resolvedContext{}, errors.New("chat id is required")
}
skipHistory := req.MaxContextLoadTime < 0
botSettings, err := r.loadBotSettings(ctx, req.BotID)
if err != nil {
return resolvedContext{}, err
@@ -176,55 +174,23 @@ func (r *Resolver) resolve(ctx context.Context, req conversation.ChatRequest) (r
}
clientType := provider.ClientType
maxCtx := coalescePositiveInt(req.MaxContextLoadTime, botSettings.MaxContextLoadTime, defaultMaxContextMinutes)
maxTokens := botSettings.MaxContextTokens
memoryMsg := r.loadMemoryContextMessage(ctx, req)
reqMessages := pruneMessagesForGateway(nonNilModelMessages(req.Messages))
if memoryMsg != nil {
pruned, _ := pruneMessageForGateway(*memoryMsg)
memoryMsg = &pruned
}
var overhead int
if memoryMsg != nil {
overhead += estimateMessageTokens(*memoryMsg)
}
for _, m := range reqMessages {
overhead += estimateMessageTokens(m)
}
const systemPromptReserve = 4096
overhead += systemPromptReserve
historyBudget := maxTokens - overhead
if maxTokens > 0 && historyBudget <= 0 {
historyBudget = 1
} else if historyBudget < 0 {
historyBudget = 0
}
r.logger.Debug("context token budget",
slog.Int("max_tokens", maxTokens),
slog.Int("overhead", overhead),
slog.Int("system_prompt_reserve", systemPromptReserve),
slog.Int("history_budget", historyBudget),
)
var messages []conversation.ModelMessage
if !skipHistory && r.conversationSvc != nil {
loaded, loadErr := r.loadMessages(ctx, req.ChatID, req.SessionID, maxCtx)
if r.conversationSvc != nil {
loaded, loadErr := r.loadMessages(ctx, req.ChatID, req.SessionID, defaultMaxContextMinutes)
if loadErr != nil {
return resolvedContext{}, loadErr
}
loaded = pruneHistoryForGateway(loaded)
loaded = dedupePersistedCurrentUserMessage(loaded, req)
loaded = r.replaceCompactedMessages(ctx, loaded)
messages = trimMessagesByTokens(r.logger, loaded, historyBudget)
r.logger.Debug("context trim result",
slog.Int("loaded_messages", len(loaded)),
slog.Int("kept_messages", len(messages)),
slog.Int("trimmed_messages", len(loaded)-len(messages)),
slog.Int("history_budget", historyBudget),
)
messages = trimMessagesByTokens(r.logger, loaded, 0)
}
if memoryMsg != nil {
messages = append(messages, *memoryMsg)
@@ -153,15 +153,6 @@ func decodeIndexedByteObject(raw json.RawMessage) ([]byte, bool) {
return out, true
}
func coalescePositiveInt(values ...int) int {
for _, v := range values {
if v > 0 {
return v
}
}
return defaultMaxContextMinutes
}
func nonNilModelMessages(m []conversation.ModelMessage) []conversation.ModelMessage {
if m == nil {
return []conversation.ModelMessage{}
+7 -8
View File
@@ -241,14 +241,13 @@ type ChatRequest struct {
// Set by the inbound channel processor; called by the resolver at persist time.
OutboundAssetCollector func() []OutboundAssetRef `json:"-"`
Query string `json:"query"`
Model string `json:"model,omitempty"`
Provider string `json:"provider,omitempty"`
MaxContextLoadTime int `json:"max_context_load_time,omitempty"`
Channels []string `json:"channels,omitempty"`
CurrentChannel string `json:"current_channel,omitempty"`
Messages []ModelMessage `json:"messages,omitempty"`
Attachments []ChatAttachment `json:"attachments,omitempty"`
Query string `json:"query"`
Model string `json:"model,omitempty"`
Provider string `json:"provider,omitempty"`
Channels []string `json:"channels,omitempty"`
CurrentChannel string `json:"current_channel,omitempty"`
Messages []ModelMessage `json:"messages,omitempty"`
Attachments []ChatAttachment `json:"attachments,omitempty"`
}
// ChatResponse is the output of a non-streaming chat call.
+81 -101
View File
@@ -14,7 +14,7 @@ import (
const createBot = `-- name: CreateBot :one
INSERT INTO bots (owner_user_id, display_name, avatar_url, timezone, is_active, metadata, status)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, max_context_load_time, max_context_tokens, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at
`
type CreateBotParams struct {
@@ -28,27 +28,25 @@ type CreateBotParams struct {
}
type CreateBotRow struct {
ID pgtype.UUID `json:"id"`
OwnerUserID pgtype.UUID `json:"owner_user_id"`
DisplayName pgtype.Text `json:"display_name"`
AvatarUrl pgtype.Text `json:"avatar_url"`
Timezone pgtype.Text `json:"timezone"`
IsActive bool `json:"is_active"`
Status string `json:"status"`
MaxContextLoadTime int32 `json:"max_context_load_time"`
MaxContextTokens int32 `json:"max_context_tokens"`
Language string `json:"language"`
ReasoningEnabled bool `json:"reasoning_enabled"`
ReasoningEffort string `json:"reasoning_effort"`
ChatModelID pgtype.UUID `json:"chat_model_id"`
SearchProviderID pgtype.UUID `json:"search_provider_id"`
MemoryProviderID pgtype.UUID `json:"memory_provider_id"`
HeartbeatEnabled bool `json:"heartbeat_enabled"`
HeartbeatInterval int32 `json:"heartbeat_interval"`
HeartbeatPrompt string `json:"heartbeat_prompt"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ID pgtype.UUID `json:"id"`
OwnerUserID pgtype.UUID `json:"owner_user_id"`
DisplayName pgtype.Text `json:"display_name"`
AvatarUrl pgtype.Text `json:"avatar_url"`
Timezone pgtype.Text `json:"timezone"`
IsActive bool `json:"is_active"`
Status string `json:"status"`
Language string `json:"language"`
ReasoningEnabled bool `json:"reasoning_enabled"`
ReasoningEffort string `json:"reasoning_effort"`
ChatModelID pgtype.UUID `json:"chat_model_id"`
SearchProviderID pgtype.UUID `json:"search_provider_id"`
MemoryProviderID pgtype.UUID `json:"memory_provider_id"`
HeartbeatEnabled bool `json:"heartbeat_enabled"`
HeartbeatInterval int32 `json:"heartbeat_interval"`
HeartbeatPrompt string `json:"heartbeat_prompt"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
func (q *Queries) CreateBot(ctx context.Context, arg CreateBotParams) (CreateBotRow, error) {
@@ -70,8 +68,6 @@ func (q *Queries) CreateBot(ctx context.Context, arg CreateBotParams) (CreateBot
&i.Timezone,
&i.IsActive,
&i.Status,
&i.MaxContextLoadTime,
&i.MaxContextTokens,
&i.Language,
&i.ReasoningEnabled,
&i.ReasoningEffort,
@@ -98,7 +94,7 @@ func (q *Queries) DeleteBotByID(ctx context.Context, id pgtype.UUID) error {
}
const getBotByID = `-- name: GetBotByID :one
SELECT id, owner_user_id, display_name, avatar_url, timezone, is_active, status, max_context_load_time, max_context_tokens, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, compaction_enabled, compaction_threshold, compaction_model_id, metadata, created_at, updated_at
SELECT id, owner_user_id, display_name, avatar_url, timezone, is_active, status, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, compaction_enabled, compaction_threshold, compaction_model_id, metadata, created_at, updated_at
FROM bots
WHERE id = $1
`
@@ -111,8 +107,6 @@ type GetBotByIDRow struct {
Timezone pgtype.Text `json:"timezone"`
IsActive bool `json:"is_active"`
Status string `json:"status"`
MaxContextLoadTime int32 `json:"max_context_load_time"`
MaxContextTokens int32 `json:"max_context_tokens"`
Language string `json:"language"`
ReasoningEnabled bool `json:"reasoning_enabled"`
ReasoningEffort string `json:"reasoning_effort"`
@@ -141,8 +135,6 @@ func (q *Queries) GetBotByID(ctx context.Context, id pgtype.UUID) (GetBotByIDRow
&i.Timezone,
&i.IsActive,
&i.Status,
&i.MaxContextLoadTime,
&i.MaxContextTokens,
&i.Language,
&i.ReasoningEnabled,
&i.ReasoningEffort,
@@ -163,34 +155,32 @@ func (q *Queries) GetBotByID(ctx context.Context, id pgtype.UUID) (GetBotByIDRow
}
const listBotsByOwner = `-- name: ListBotsByOwner :many
SELECT id, owner_user_id, display_name, avatar_url, timezone, is_active, status, max_context_load_time, max_context_tokens, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at
SELECT id, owner_user_id, display_name, avatar_url, timezone, is_active, status, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at
FROM bots
WHERE owner_user_id = $1
ORDER BY created_at DESC
`
type ListBotsByOwnerRow struct {
ID pgtype.UUID `json:"id"`
OwnerUserID pgtype.UUID `json:"owner_user_id"`
DisplayName pgtype.Text `json:"display_name"`
AvatarUrl pgtype.Text `json:"avatar_url"`
Timezone pgtype.Text `json:"timezone"`
IsActive bool `json:"is_active"`
Status string `json:"status"`
MaxContextLoadTime int32 `json:"max_context_load_time"`
MaxContextTokens int32 `json:"max_context_tokens"`
Language string `json:"language"`
ReasoningEnabled bool `json:"reasoning_enabled"`
ReasoningEffort string `json:"reasoning_effort"`
ChatModelID pgtype.UUID `json:"chat_model_id"`
SearchProviderID pgtype.UUID `json:"search_provider_id"`
MemoryProviderID pgtype.UUID `json:"memory_provider_id"`
HeartbeatEnabled bool `json:"heartbeat_enabled"`
HeartbeatInterval int32 `json:"heartbeat_interval"`
HeartbeatPrompt string `json:"heartbeat_prompt"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ID pgtype.UUID `json:"id"`
OwnerUserID pgtype.UUID `json:"owner_user_id"`
DisplayName pgtype.Text `json:"display_name"`
AvatarUrl pgtype.Text `json:"avatar_url"`
Timezone pgtype.Text `json:"timezone"`
IsActive bool `json:"is_active"`
Status string `json:"status"`
Language string `json:"language"`
ReasoningEnabled bool `json:"reasoning_enabled"`
ReasoningEffort string `json:"reasoning_effort"`
ChatModelID pgtype.UUID `json:"chat_model_id"`
SearchProviderID pgtype.UUID `json:"search_provider_id"`
MemoryProviderID pgtype.UUID `json:"memory_provider_id"`
HeartbeatEnabled bool `json:"heartbeat_enabled"`
HeartbeatInterval int32 `json:"heartbeat_interval"`
HeartbeatPrompt string `json:"heartbeat_prompt"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
func (q *Queries) ListBotsByOwner(ctx context.Context, ownerUserID pgtype.UUID) ([]ListBotsByOwnerRow, error) {
@@ -210,8 +200,6 @@ func (q *Queries) ListBotsByOwner(ctx context.Context, ownerUserID pgtype.UUID)
&i.Timezone,
&i.IsActive,
&i.Status,
&i.MaxContextLoadTime,
&i.MaxContextTokens,
&i.Language,
&i.ReasoningEnabled,
&i.ReasoningEffort,
@@ -280,7 +268,7 @@ UPDATE bots
SET owner_user_id = $2,
updated_at = now()
WHERE id = $1
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, max_context_load_time, max_context_tokens, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at
`
type UpdateBotOwnerParams struct {
@@ -289,27 +277,25 @@ type UpdateBotOwnerParams struct {
}
type UpdateBotOwnerRow struct {
ID pgtype.UUID `json:"id"`
OwnerUserID pgtype.UUID `json:"owner_user_id"`
DisplayName pgtype.Text `json:"display_name"`
AvatarUrl pgtype.Text `json:"avatar_url"`
Timezone pgtype.Text `json:"timezone"`
IsActive bool `json:"is_active"`
Status string `json:"status"`
MaxContextLoadTime int32 `json:"max_context_load_time"`
MaxContextTokens int32 `json:"max_context_tokens"`
Language string `json:"language"`
ReasoningEnabled bool `json:"reasoning_enabled"`
ReasoningEffort string `json:"reasoning_effort"`
ChatModelID pgtype.UUID `json:"chat_model_id"`
SearchProviderID pgtype.UUID `json:"search_provider_id"`
MemoryProviderID pgtype.UUID `json:"memory_provider_id"`
HeartbeatEnabled bool `json:"heartbeat_enabled"`
HeartbeatInterval int32 `json:"heartbeat_interval"`
HeartbeatPrompt string `json:"heartbeat_prompt"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ID pgtype.UUID `json:"id"`
OwnerUserID pgtype.UUID `json:"owner_user_id"`
DisplayName pgtype.Text `json:"display_name"`
AvatarUrl pgtype.Text `json:"avatar_url"`
Timezone pgtype.Text `json:"timezone"`
IsActive bool `json:"is_active"`
Status string `json:"status"`
Language string `json:"language"`
ReasoningEnabled bool `json:"reasoning_enabled"`
ReasoningEffort string `json:"reasoning_effort"`
ChatModelID pgtype.UUID `json:"chat_model_id"`
SearchProviderID pgtype.UUID `json:"search_provider_id"`
MemoryProviderID pgtype.UUID `json:"memory_provider_id"`
HeartbeatEnabled bool `json:"heartbeat_enabled"`
HeartbeatInterval int32 `json:"heartbeat_interval"`
HeartbeatPrompt string `json:"heartbeat_prompt"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
func (q *Queries) UpdateBotOwner(ctx context.Context, arg UpdateBotOwnerParams) (UpdateBotOwnerRow, error) {
@@ -323,8 +309,6 @@ func (q *Queries) UpdateBotOwner(ctx context.Context, arg UpdateBotOwnerParams)
&i.Timezone,
&i.IsActive,
&i.Status,
&i.MaxContextLoadTime,
&i.MaxContextTokens,
&i.Language,
&i.ReasoningEnabled,
&i.ReasoningEffort,
@@ -350,7 +334,7 @@ SET display_name = $2,
metadata = $6,
updated_at = now()
WHERE id = $1
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, max_context_load_time, max_context_tokens, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, metadata, created_at, updated_at
`
type UpdateBotProfileParams struct {
@@ -363,27 +347,25 @@ type UpdateBotProfileParams struct {
}
type UpdateBotProfileRow struct {
ID pgtype.UUID `json:"id"`
OwnerUserID pgtype.UUID `json:"owner_user_id"`
DisplayName pgtype.Text `json:"display_name"`
AvatarUrl pgtype.Text `json:"avatar_url"`
Timezone pgtype.Text `json:"timezone"`
IsActive bool `json:"is_active"`
Status string `json:"status"`
MaxContextLoadTime int32 `json:"max_context_load_time"`
MaxContextTokens int32 `json:"max_context_tokens"`
Language string `json:"language"`
ReasoningEnabled bool `json:"reasoning_enabled"`
ReasoningEffort string `json:"reasoning_effort"`
ChatModelID pgtype.UUID `json:"chat_model_id"`
SearchProviderID pgtype.UUID `json:"search_provider_id"`
MemoryProviderID pgtype.UUID `json:"memory_provider_id"`
HeartbeatEnabled bool `json:"heartbeat_enabled"`
HeartbeatInterval int32 `json:"heartbeat_interval"`
HeartbeatPrompt string `json:"heartbeat_prompt"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ID pgtype.UUID `json:"id"`
OwnerUserID pgtype.UUID `json:"owner_user_id"`
DisplayName pgtype.Text `json:"display_name"`
AvatarUrl pgtype.Text `json:"avatar_url"`
Timezone pgtype.Text `json:"timezone"`
IsActive bool `json:"is_active"`
Status string `json:"status"`
Language string `json:"language"`
ReasoningEnabled bool `json:"reasoning_enabled"`
ReasoningEffort string `json:"reasoning_effort"`
ChatModelID pgtype.UUID `json:"chat_model_id"`
SearchProviderID pgtype.UUID `json:"search_provider_id"`
MemoryProviderID pgtype.UUID `json:"memory_provider_id"`
HeartbeatEnabled bool `json:"heartbeat_enabled"`
HeartbeatInterval int32 `json:"heartbeat_interval"`
HeartbeatPrompt string `json:"heartbeat_prompt"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
func (q *Queries) UpdateBotProfile(ctx context.Context, arg UpdateBotProfileParams) (UpdateBotProfileRow, error) {
@@ -404,8 +386,6 @@ func (q *Queries) UpdateBotProfile(ctx context.Context, arg UpdateBotProfilePara
&i.Timezone,
&i.IsActive,
&i.Status,
&i.MaxContextLoadTime,
&i.MaxContextTokens,
&i.Language,
&i.ReasoningEnabled,
&i.ReasoningEffort,
+1 -1
View File
@@ -511,7 +511,7 @@ WITH updated AS (
SET display_name = $1,
updated_at = now()
WHERE bots.id = $2
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, max_context_load_time, max_context_tokens, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, heartbeat_model_id, compaction_enabled, compaction_threshold, compaction_model_id, title_model_id, tts_model_id, browser_context_id, metadata, created_at, updated_at, acl_default_effect
RETURNING id, owner_user_id, display_name, avatar_url, timezone, is_active, status, language, reasoning_enabled, reasoning_effort, chat_model_id, search_provider_id, memory_provider_id, heartbeat_enabled, heartbeat_interval, heartbeat_prompt, heartbeat_model_id, compaction_enabled, compaction_threshold, compaction_model_id, title_model_id, tts_model_id, browser_context_id, metadata, created_at, updated_at, acl_default_effect
)
SELECT
updated.id AS id,
-2
View File
@@ -16,8 +16,6 @@ type Bot struct {
Timezone pgtype.Text `json:"timezone"`
IsActive bool `json:"is_active"`
Status string `json:"status"`
MaxContextLoadTime int32 `json:"max_context_load_time"`
MaxContextTokens int32 `json:"max_context_tokens"`
Language string `json:"language"`
ReasoningEnabled bool `json:"reasoning_enabled"`
ReasoningEffort string `json:"reasoning_effort"`
+19 -39
View File
@@ -13,9 +13,7 @@ import (
const deleteSettingsByBotID = `-- name: DeleteSettingsByBotID :exec
UPDATE bots
SET max_context_load_time = 1440,
max_context_tokens = 0,
language = 'auto',
SET language = 'auto',
reasoning_enabled = false,
reasoning_effort = 'medium',
heartbeat_enabled = false,
@@ -43,8 +41,6 @@ func (q *Queries) DeleteSettingsByBotID(ctx context.Context, id pgtype.UUID) err
const getSettingsByBotID = `-- name: GetSettingsByBotID :one
SELECT
bots.id AS bot_id,
bots.max_context_load_time,
bots.max_context_tokens,
bots.language,
bots.reasoning_enabled,
bots.reasoning_effort,
@@ -75,8 +71,6 @@ WHERE bots.id = $1
type GetSettingsByBotIDRow struct {
BotID pgtype.UUID `json:"bot_id"`
MaxContextLoadTime int32 `json:"max_context_load_time"`
MaxContextTokens int32 `json:"max_context_tokens"`
Language string `json:"language"`
ReasoningEnabled bool `json:"reasoning_enabled"`
ReasoningEffort string `json:"reasoning_effort"`
@@ -100,8 +94,6 @@ func (q *Queries) GetSettingsByBotID(ctx context.Context, id pgtype.UUID) (GetSe
var i GetSettingsByBotIDRow
err := row.Scan(
&i.BotID,
&i.MaxContextLoadTime,
&i.MaxContextTokens,
&i.Language,
&i.ReasoningEnabled,
&i.ReasoningEffort,
@@ -125,32 +117,28 @@ func (q *Queries) GetSettingsByBotID(ctx context.Context, id pgtype.UUID) (GetSe
const upsertBotSettings = `-- name: UpsertBotSettings :one
WITH updated AS (
UPDATE bots
SET max_context_load_time = $1,
max_context_tokens = $2,
language = $3,
reasoning_enabled = $4,
reasoning_effort = $5,
heartbeat_enabled = $6,
heartbeat_interval = $7,
heartbeat_prompt = $8,
compaction_enabled = $9,
compaction_threshold = $10,
chat_model_id = COALESCE($11::uuid, bots.chat_model_id),
heartbeat_model_id = COALESCE($12::uuid, bots.heartbeat_model_id),
compaction_model_id = COALESCE($13::uuid, bots.compaction_model_id),
title_model_id = COALESCE($14::uuid, bots.title_model_id),
search_provider_id = COALESCE($15::uuid, bots.search_provider_id),
memory_provider_id = COALESCE($16::uuid, bots.memory_provider_id),
tts_model_id = COALESCE($17::uuid, bots.tts_model_id),
browser_context_id = COALESCE($18::uuid, bots.browser_context_id),
SET language = $1,
reasoning_enabled = $2,
reasoning_effort = $3,
heartbeat_enabled = $4,
heartbeat_interval = $5,
heartbeat_prompt = $6,
compaction_enabled = $7,
compaction_threshold = $8,
chat_model_id = COALESCE($9::uuid, bots.chat_model_id),
heartbeat_model_id = COALESCE($10::uuid, bots.heartbeat_model_id),
compaction_model_id = COALESCE($11::uuid, bots.compaction_model_id),
title_model_id = COALESCE($12::uuid, bots.title_model_id),
search_provider_id = COALESCE($13::uuid, bots.search_provider_id),
memory_provider_id = COALESCE($14::uuid, bots.memory_provider_id),
tts_model_id = COALESCE($15::uuid, bots.tts_model_id),
browser_context_id = COALESCE($16::uuid, bots.browser_context_id),
updated_at = now()
WHERE bots.id = $19
RETURNING bots.id, bots.max_context_load_time, bots.max_context_tokens, bots.language, bots.reasoning_enabled, bots.reasoning_effort, bots.heartbeat_enabled, bots.heartbeat_interval, bots.heartbeat_prompt, bots.compaction_enabled, bots.compaction_threshold, bots.chat_model_id, bots.heartbeat_model_id, bots.compaction_model_id, bots.title_model_id, bots.search_provider_id, bots.memory_provider_id, bots.tts_model_id, bots.browser_context_id
WHERE bots.id = $17
RETURNING bots.id, bots.language, bots.reasoning_enabled, bots.reasoning_effort, bots.heartbeat_enabled, bots.heartbeat_interval, bots.heartbeat_prompt, bots.compaction_enabled, bots.compaction_threshold, bots.chat_model_id, bots.heartbeat_model_id, bots.compaction_model_id, bots.title_model_id, bots.search_provider_id, bots.memory_provider_id, bots.tts_model_id, bots.browser_context_id
)
SELECT
updated.id AS bot_id,
updated.max_context_load_time,
updated.max_context_tokens,
updated.language,
updated.reasoning_enabled,
updated.reasoning_effort,
@@ -179,8 +167,6 @@ LEFT JOIN browser_contexts ON browser_contexts.id = updated.browser_context_id
`
type UpsertBotSettingsParams struct {
MaxContextLoadTime int32 `json:"max_context_load_time"`
MaxContextTokens int32 `json:"max_context_tokens"`
Language string `json:"language"`
ReasoningEnabled bool `json:"reasoning_enabled"`
ReasoningEffort string `json:"reasoning_effort"`
@@ -202,8 +188,6 @@ type UpsertBotSettingsParams struct {
type UpsertBotSettingsRow struct {
BotID pgtype.UUID `json:"bot_id"`
MaxContextLoadTime int32 `json:"max_context_load_time"`
MaxContextTokens int32 `json:"max_context_tokens"`
Language string `json:"language"`
ReasoningEnabled bool `json:"reasoning_enabled"`
ReasoningEffort string `json:"reasoning_effort"`
@@ -224,8 +208,6 @@ type UpsertBotSettingsRow struct {
func (q *Queries) UpsertBotSettings(ctx context.Context, arg UpsertBotSettingsParams) (UpsertBotSettingsRow, error) {
row := q.db.QueryRow(ctx, upsertBotSettings,
arg.MaxContextLoadTime,
arg.MaxContextTokens,
arg.Language,
arg.ReasoningEnabled,
arg.ReasoningEffort,
@@ -247,8 +229,6 @@ func (q *Queries) UpsertBotSettings(ctx context.Context, arg UpsertBotSettingsPa
var i UpsertBotSettingsRow
err := row.Scan(
&i.BotID,
&i.MaxContextLoadTime,
&i.MaxContextTokens,
&i.Language,
&i.ReasoningEnabled,
&i.ReasoningEffort,
+5 -35
View File
@@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"log/slog"
"math"
"strings"
"github.com/google/uuid"
@@ -70,13 +69,7 @@ func (s *Service) UpsertBot(ctx context.Context, botID string, req UpsertRequest
if err != nil {
return Settings{}, err
}
current := normalizeBotSetting(botRow.MaxContextLoadTime, botRow.MaxContextTokens, botRow.Language, aclDefaultEffect, botRow.ReasoningEnabled, botRow.ReasoningEffort, botRow.HeartbeatEnabled, botRow.HeartbeatInterval, botRow.CompactionEnabled, botRow.CompactionThreshold)
if req.MaxContextLoadTime != nil && *req.MaxContextLoadTime > 0 {
current.MaxContextLoadTime = *req.MaxContextLoadTime
}
if req.MaxContextTokens != nil && *req.MaxContextTokens >= 0 {
current.MaxContextTokens = *req.MaxContextTokens
}
current := normalizeBotSetting(botRow.Language, aclDefaultEffect, botRow.ReasoningEnabled, botRow.ReasoningEffort, botRow.HeartbeatEnabled, botRow.HeartbeatInterval, botRow.CompactionEnabled, botRow.CompactionThreshold)
if strings.TrimSpace(req.Language) != "" {
current.Language = strings.TrimSpace(req.Language)
}
@@ -167,25 +160,16 @@ func (s *Service) UpsertBot(ctx context.Context, botID string, req UpsertRequest
}
browserContextUUID = ctxID
}
if current.MaxContextLoadTime < math.MinInt32 || current.MaxContextLoadTime > math.MaxInt32 ||
current.MaxContextTokens < math.MinInt32 || current.MaxContextTokens > math.MaxInt32 ||
current.HeartbeatInterval < math.MinInt32 || current.HeartbeatInterval > math.MaxInt32 ||
current.CompactionThreshold < math.MinInt32 || current.CompactionThreshold > math.MaxInt32 {
return Settings{}, errors.New("settings numeric value out of int32 range")
}
updated, err := s.queries.UpsertBotSettings(ctx, sqlc.UpsertBotSettingsParams{
ID: pgID,
MaxContextLoadTime: int32(current.MaxContextLoadTime), //nolint:gosec // range validated above
MaxContextTokens: int32(current.MaxContextTokens),
Language: current.Language,
ReasoningEnabled: current.ReasoningEnabled,
ReasoningEffort: current.ReasoningEffort,
HeartbeatEnabled: current.HeartbeatEnabled,
HeartbeatInterval: int32(current.HeartbeatInterval),
HeartbeatInterval: int32(current.HeartbeatInterval), //nolint:gosec // bounded by positive-only setter above
HeartbeatPrompt: "",
CompactionEnabled: current.CompactionEnabled,
CompactionThreshold: int32(current.CompactionThreshold), //nolint:gosec // range validated above
CompactionThreshold: int32(current.CompactionThreshold), //nolint:gosec // bounded by non-negative setter above
ChatModelID: chatModelUUID,
HeartbeatModelID: heartbeatModelUUID,
CompactionModelID: compactionModelUUID,
@@ -225,10 +209,8 @@ func (s *Service) Delete(ctx context.Context, botID string) error {
return nil
}
func normalizeBotSetting(maxContextLoadTime int32, maxContextTokens int32, language string, aclDefaultEffect string, reasoningEnabled bool, reasoningEffort string, heartbeatEnabled bool, heartbeatInterval int32, compactionEnabled bool, compactionThreshold int32) Settings {
func normalizeBotSetting(language string, aclDefaultEffect string, reasoningEnabled bool, reasoningEffort string, heartbeatEnabled bool, heartbeatInterval int32, compactionEnabled bool, compactionThreshold int32) Settings {
settings := Settings{
MaxContextLoadTime: int(maxContextLoadTime),
MaxContextTokens: int(maxContextTokens),
Language: strings.TrimSpace(language),
AclDefaultEffect: strings.TrimSpace(aclDefaultEffect),
ReasoningEnabled: reasoningEnabled,
@@ -238,12 +220,6 @@ func normalizeBotSetting(maxContextLoadTime int32, maxContextTokens int32, langu
CompactionEnabled: compactionEnabled,
CompactionThreshold: int(compactionThreshold),
}
if settings.MaxContextLoadTime <= 0 {
settings.MaxContextLoadTime = DefaultMaxContextLoadTime
}
if settings.MaxContextTokens < 0 {
settings.MaxContextTokens = 0
}
if settings.Language == "" {
settings.Language = DefaultLanguage
}
@@ -273,8 +249,6 @@ func isValidReasoningEffort(effort string) bool {
func normalizeBotSettingsReadRow(row sqlc.GetSettingsByBotIDRow) Settings {
return normalizeBotSettingsFields(
row.MaxContextLoadTime,
row.MaxContextTokens,
row.Language,
row.ReasoningEnabled,
row.ReasoningEffort,
@@ -295,8 +269,6 @@ func normalizeBotSettingsReadRow(row sqlc.GetSettingsByBotIDRow) Settings {
func normalizeBotSettingsWriteRow(row sqlc.UpsertBotSettingsRow) Settings {
return normalizeBotSettingsFields(
row.MaxContextLoadTime,
row.MaxContextTokens,
row.Language,
row.ReasoningEnabled,
row.ReasoningEffort,
@@ -316,8 +288,6 @@ func normalizeBotSettingsWriteRow(row sqlc.UpsertBotSettingsRow) Settings {
}
func normalizeBotSettingsFields(
maxContextLoadTime int32,
maxContextTokens int32,
language string,
reasoningEnabled bool,
reasoningEffort string,
@@ -334,7 +304,7 @@ func normalizeBotSettingsFields(
ttsModelID pgtype.UUID,
browserContextID pgtype.UUID,
) Settings {
settings := normalizeBotSetting(maxContextLoadTime, maxContextTokens, language, "", reasoningEnabled, reasoningEffort, heartbeatEnabled, heartbeatInterval, compactionEnabled, compactionThreshold)
settings := normalizeBotSetting(language, "", reasoningEnabled, reasoningEffort, heartbeatEnabled, heartbeatInterval, compactionEnabled, compactionThreshold)
if chatModelID.Valid {
settings.ChatModelID = uuid.UUID(chatModelID.Bytes).String()
}
+3 -8
View File
@@ -1,10 +1,9 @@
package settings
const (
DefaultMaxContextLoadTime = 24 * 60
DefaultLanguage = "auto"
DefaultReasoningEffort = "medium"
DefaultHeartbeatInterval = 30
DefaultLanguage = "auto"
DefaultReasoningEffort = "medium"
DefaultHeartbeatInterval = 30
)
type Settings struct {
@@ -13,8 +12,6 @@ type Settings struct {
MemoryProviderID string `json:"memory_provider_id"`
TtsModelID string `json:"tts_model_id"`
BrowserContextID string `json:"browser_context_id"`
MaxContextLoadTime int `json:"max_context_load_time"`
MaxContextTokens int `json:"max_context_tokens"`
Language string `json:"language"`
AclDefaultEffect string `json:"acl_default_effect"`
ReasoningEnabled bool `json:"reasoning_enabled"`
@@ -34,8 +31,6 @@ type UpsertRequest struct {
MemoryProviderID string `json:"memory_provider_id,omitempty"`
TtsModelID string `json:"tts_model_id,omitempty"`
BrowserContextID string `json:"browser_context_id,omitempty"`
MaxContextLoadTime *int `json:"max_context_load_time,omitempty"`
MaxContextTokens *int `json:"max_context_tokens,omitempty"`
Language string `json:"language,omitempty"`
AclDefaultEffect string `json:"acl_default_effect,omitempty"`
ReasoningEnabled *bool `json:"reasoning_enabled,omitempty"`
-4
View File
@@ -1447,8 +1447,6 @@ export type SettingsSettings = {
heartbeat_interval?: number;
heartbeat_model_id?: string;
language?: string;
max_context_load_time?: number;
max_context_tokens?: number;
memory_provider_id?: string;
reasoning_effort?: string;
reasoning_enabled?: boolean;
@@ -1468,8 +1466,6 @@ export type SettingsUpsertRequest = {
heartbeat_interval?: number;
heartbeat_model_id?: string;
language?: string;
max_context_load_time?: number;
max_context_tokens?: number;
memory_provider_id?: string;
reasoning_effort?: string;
reasoning_enabled?: boolean;
-12
View File
@@ -12397,12 +12397,6 @@ const docTemplate = `{
"language": {
"type": "string"
},
"max_context_load_time": {
"type": "integer"
},
"max_context_tokens": {
"type": "integer"
},
"memory_provider_id": {
"type": "string"
},
@@ -12456,12 +12450,6 @@ const docTemplate = `{
"language": {
"type": "string"
},
"max_context_load_time": {
"type": "integer"
},
"max_context_tokens": {
"type": "integer"
},
"memory_provider_id": {
"type": "string"
},
-12
View File
@@ -12388,12 +12388,6 @@
"language": {
"type": "string"
},
"max_context_load_time": {
"type": "integer"
},
"max_context_tokens": {
"type": "integer"
},
"memory_provider_id": {
"type": "string"
},
@@ -12447,12 +12441,6 @@
"language": {
"type": "string"
},
"max_context_load_time": {
"type": "integer"
},
"max_context_tokens": {
"type": "integer"
},
"memory_provider_id": {
"type": "string"
},
-8
View File
@@ -2398,10 +2398,6 @@ definitions:
type: string
language:
type: string
max_context_load_time:
type: integer
max_context_tokens:
type: integer
memory_provider_id:
type: string
reasoning_effort:
@@ -2437,10 +2433,6 @@ definitions:
type: string
language:
type: string
max_context_load_time:
type: integer
max_context_tokens:
type: integer
memory_provider_id:
type: string
reasoning_effort: