[codex] Harden context compression history handling (#848)
* Use token threshold for chat compression * Add compression settings controls * Use config for chat compression * Cover protected messages in compression tests * Remove message-count compression limit * Harden compression window fallback * Rebuild stale compression snapshots * Harden stale compression snapshots * Update changelog for compression hardening * Prefer local history session details
This commit is contained in:
@@ -28,6 +28,14 @@ export interface MemoryConfig {
|
||||
user_char_limit?: number
|
||||
}
|
||||
|
||||
export interface CompressionConfig {
|
||||
enabled?: boolean
|
||||
threshold?: number
|
||||
target_ratio?: number
|
||||
protect_last_n?: number
|
||||
protect_first_n?: number
|
||||
}
|
||||
|
||||
export interface SessionResetConfig {
|
||||
mode?: string
|
||||
idle_minutes?: number
|
||||
@@ -47,6 +55,7 @@ export interface AppConfig {
|
||||
display?: DisplayConfig
|
||||
agent?: AgentConfig
|
||||
memory?: MemoryConfig
|
||||
compression?: CompressionConfig
|
||||
session_reset?: SessionResetConfig
|
||||
privacy?: PrivacyConfig
|
||||
approvals?: ApprovalConfig
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
<script setup lang="ts">
|
||||
import { NInputNumber, NSwitch, useMessage } from 'naive-ui'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useSettingsStore } from '@/stores/hermes/settings'
|
||||
import SettingRow from './SettingRow.vue'
|
||||
|
||||
const settingsStore = useSettingsStore()
|
||||
const message = useMessage()
|
||||
const { t } = useI18n()
|
||||
|
||||
const defaults = {
|
||||
enabled: true,
|
||||
threshold: 0.5,
|
||||
target_ratio: 0.2,
|
||||
protect_last_n: 20,
|
||||
protect_first_n: 3,
|
||||
}
|
||||
|
||||
const debounceTimers: Record<string, ReturnType<typeof setTimeout>> = {}
|
||||
|
||||
function save(values: Record<string, any>) {
|
||||
settingsStore.updateLocal('compression', values)
|
||||
settingsStore.saveSection('compression', values).then(() => {
|
||||
message.success(t('settings.saved'))
|
||||
}).catch(() => {
|
||||
message.error(t('settings.saveFailed'))
|
||||
})
|
||||
}
|
||||
|
||||
function debouncedSave(key: string, value: any) {
|
||||
settingsStore.updateLocal('compression', { [key]: value })
|
||||
if (debounceTimers[key]) clearTimeout(debounceTimers[key])
|
||||
debounceTimers[key] = setTimeout(async () => {
|
||||
try {
|
||||
await settingsStore.saveSection('compression', { [key]: value })
|
||||
message.success(t('settings.saved'))
|
||||
} catch {
|
||||
message.error(t('settings.saveFailed'))
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="settings-section">
|
||||
<SettingRow :label="t('settings.compression.enabled')" :hint="t('settings.compression.enabledHint')">
|
||||
<NSwitch
|
||||
:value="settingsStore.compression.enabled ?? defaults.enabled"
|
||||
size="small"
|
||||
@update:value="v => save({ enabled: v })"
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow :label="t('settings.compression.threshold')" :hint="t('settings.compression.thresholdHint')">
|
||||
<NInputNumber
|
||||
:value="settingsStore.compression.threshold ?? defaults.threshold"
|
||||
:min="0.1"
|
||||
:max="0.95"
|
||||
:step="0.05"
|
||||
size="small"
|
||||
class="input-sm"
|
||||
@update:value="v => v != null && debouncedSave('threshold', v)"
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow :label="t('settings.compression.targetRatio')" :hint="t('settings.compression.targetRatioHint')">
|
||||
<NInputNumber
|
||||
:value="settingsStore.compression.target_ratio ?? defaults.target_ratio"
|
||||
:min="0.05"
|
||||
:max="0.8"
|
||||
:step="0.05"
|
||||
size="small"
|
||||
class="input-sm"
|
||||
@update:value="v => v != null && debouncedSave('target_ratio', v)"
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow :label="t('settings.compression.protectLastN')" :hint="t('settings.compression.protectLastNHint')">
|
||||
<NInputNumber
|
||||
:value="settingsStore.compression.protect_last_n ?? defaults.protect_last_n"
|
||||
:min="0"
|
||||
:max="200"
|
||||
:step="1"
|
||||
size="small"
|
||||
class="input-sm"
|
||||
@update:value="v => v != null && debouncedSave('protect_last_n', v)"
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow :label="t('settings.compression.protectFirstN')" :hint="t('settings.compression.protectFirstNHint')">
|
||||
<NInputNumber
|
||||
:value="settingsStore.compression.protect_first_n ?? defaults.protect_first_n"
|
||||
:min="0"
|
||||
:max="50"
|
||||
:step="1"
|
||||
size="small"
|
||||
class="input-sm"
|
||||
@update:value="v => v != null && debouncedSave('protect_first_n', v)"
|
||||
/>
|
||||
</SettingRow>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use '@/styles/variables' as *;
|
||||
|
||||
.settings-section {
|
||||
margin-top: 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -17,6 +17,7 @@ export const changelog: ChangelogEntry[] = [
|
||||
'changelog.new_0_5_30_6',
|
||||
'changelog.new_0_5_30_7',
|
||||
'changelog.new_0_5_30_8',
|
||||
'changelog.new_0_5_30_9',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -549,6 +549,7 @@ jobTriggered: 'Job ausgelost',
|
||||
account: 'Konto',
|
||||
agent: 'Agent',
|
||||
memory: 'Gedachtnis',
|
||||
compression: 'Komprimierung',
|
||||
session: 'Sitzung',
|
||||
privacy: 'Datenschutz',
|
||||
apiServer: 'API-Server',
|
||||
@@ -599,6 +600,18 @@ jobTriggered: 'Job ausgelost',
|
||||
userCharLimit: 'Zeichenlimit fur Benutzerprofil',
|
||||
userCharLimitHint: 'Maximale Zeichen fur USER.md',
|
||||
},
|
||||
compression: {
|
||||
enabled: 'Komprimierung aktivieren',
|
||||
enabledHint: 'Langen Chatverlauf automatisch komprimieren, bevor der Modellkontext uberschritten wird',
|
||||
threshold: 'Komprimierungsschwelle',
|
||||
thresholdHint: 'Komprimierung starten, wenn geschatzte Token dieses Kontextverhaltnis uberschreiten',
|
||||
targetRatio: 'Zielverhaltnis',
|
||||
targetRatioHint: 'Zielgroße des Verlaufs nach der Komprimierung als Kontextverhaltnis',
|
||||
protectLastN: 'Neueste Nachrichten schutzen',
|
||||
protectLastNHint: 'So viele neueste Nachrichten unkomprimiert lassen',
|
||||
protectFirstN: 'Erste Nachrichten schutzen',
|
||||
protectFirstNHint: 'So viele erste Nachrichten unkomprimiert lassen',
|
||||
},
|
||||
session: {
|
||||
mode: 'Zurucksetzungsmodus',
|
||||
modeHint: 'Ausloser fur Sitzungszurucksetzung',
|
||||
@@ -957,6 +970,7 @@ jobTriggered: 'Job ausgelost',
|
||||
new_0_5_30_6: 'Harden Windows compatibility for path detection, file downloads, and job/update subprocesses so they no longer flash terminal windows',
|
||||
new_0_5_30_7: 'Fix config writes and provider presets: validate .env keys, route FUN-Codex through the Responses API, and refresh Z.AI/GLM model lists',
|
||||
new_0_5_30_8: 'Polish frontend details including collapsed sidebar layout, short group labels, sidebar divider, and conversation outline styling',
|
||||
new_0_5_30_9: 'Context compression now follows Profile compression settings and hardens stale snapshots by reusing previous summaries with a safe tail instead of recompressing full history',
|
||||
new_0_5_5_1: '🎉 Tag der Arbeit! Heute wird nicht gearbeitet, bitte habt Verständnis',
|
||||
new_0_5_5_2: 'Verlaufsseite für Hermes-Sitzungshistorie hinzugefügt',
|
||||
new_0_5_5_3: 'Verlaufsseite verwaltet Sitzungen unabhängig ohne Störung des aktiven Chats',
|
||||
|
||||
@@ -716,6 +716,7 @@ export default {
|
||||
account: 'Account',
|
||||
agent: 'Agent',
|
||||
memory: 'Memory',
|
||||
compression: 'Compression',
|
||||
session: 'Session',
|
||||
privacy: 'Privacy',
|
||||
apiServer: 'API Server',
|
||||
@@ -774,6 +775,18 @@ export default {
|
||||
userCharLimit: 'User Profile Char Limit',
|
||||
userCharLimitHint: 'Max characters for USER.md',
|
||||
},
|
||||
compression: {
|
||||
enabled: 'Enable Compression',
|
||||
enabledHint: 'Automatically compress long chat history before it exceeds the model context',
|
||||
threshold: 'Compression Threshold',
|
||||
thresholdHint: 'Start compression when estimated tokens exceed this context ratio',
|
||||
targetRatio: 'Target Ratio',
|
||||
targetRatioHint: 'Target history size after compression as a context ratio',
|
||||
protectLastN: 'Protect Recent Messages',
|
||||
protectLastNHint: 'Keep this many latest messages uncompressed',
|
||||
protectFirstN: 'Protect First Messages',
|
||||
protectFirstNHint: 'Keep this many earliest messages uncompressed',
|
||||
},
|
||||
session: {
|
||||
mode: 'Reset Mode',
|
||||
modeHint: 'Trigger condition for session reset',
|
||||
@@ -1251,6 +1264,7 @@ export default {
|
||||
new_0_5_30_6: 'Harden Windows compatibility for path detection, file downloads, and job/update subprocesses so they no longer flash terminal windows',
|
||||
new_0_5_30_7: 'Fix config writes and provider presets: validate .env keys, route FUN-Codex through the Responses API, and refresh Z.AI/GLM model lists',
|
||||
new_0_5_30_8: 'Polish frontend details including collapsed sidebar layout, short group labels, sidebar divider, and conversation outline styling',
|
||||
new_0_5_30_9: 'Context compression now follows Profile compression settings and hardens stale snapshots by reusing previous summaries with a safe tail instead of recompressing full history',
|
||||
|
||||
new_0_5_6_1: 'Add voice playback feature with Web Speech API: manual button, auto-play toggle, rainbow border animation, and mobile optimization',
|
||||
new_0_5_6_2: 'Add robust LLM JSON parser with tolerance for Python format and extract text from streaming events',
|
||||
|
||||
@@ -549,6 +549,7 @@ jobTriggered: 'Job ejecutado',
|
||||
account: 'Cuenta',
|
||||
agent: 'Agente',
|
||||
memory: 'Memoria',
|
||||
compression: 'Compresion',
|
||||
session: 'Sesion',
|
||||
privacy: 'Privacidad',
|
||||
apiServer: 'Servidor API',
|
||||
@@ -599,6 +600,18 @@ jobTriggered: 'Job ejecutado',
|
||||
userCharLimit: 'Limite de caracteres del perfil de usuario',
|
||||
userCharLimitHint: 'Maximo de caracteres para USER.md',
|
||||
},
|
||||
compression: {
|
||||
enabled: 'Activar compresion',
|
||||
enabledHint: 'Comprimir automaticamente el historial largo antes de superar el contexto del modelo',
|
||||
threshold: 'Umbral de compresion',
|
||||
thresholdHint: 'Iniciar compresion cuando los tokens estimados superen esta proporcion del contexto',
|
||||
targetRatio: 'Proporcion objetivo',
|
||||
targetRatioHint: 'Tamano objetivo del historial tras comprimir como proporcion del contexto',
|
||||
protectLastN: 'Proteger mensajes recientes',
|
||||
protectLastNHint: 'Mantener sin comprimir esta cantidad de mensajes recientes',
|
||||
protectFirstN: 'Proteger primeros mensajes',
|
||||
protectFirstNHint: 'Mantener sin comprimir esta cantidad de mensajes iniciales',
|
||||
},
|
||||
session: {
|
||||
mode: 'Modo de reinicio',
|
||||
modeHint: 'Condicion de activacion del reinicio de sesion',
|
||||
@@ -953,6 +966,7 @@ jobTriggered: 'Job ejecutado',
|
||||
new_0_5_30_6: 'Harden Windows compatibility for path detection, file downloads, and job/update subprocesses so they no longer flash terminal windows',
|
||||
new_0_5_30_7: 'Fix config writes and provider presets: validate .env keys, route FUN-Codex through the Responses API, and refresh Z.AI/GLM model lists',
|
||||
new_0_5_30_8: 'Polish frontend details including collapsed sidebar layout, short group labels, sidebar divider, and conversation outline styling',
|
||||
new_0_5_30_9: 'Context compression now follows Profile compression settings and hardens stale snapshots by reusing previous summaries with a safe tail instead of recompressing full history',
|
||||
new_0_5_5_1: '🎉 ¡Feliz Día del Trabajo! Hoy no se trabaja, agradezcan su comprensión',
|
||||
new_0_5_5_2: 'Añadida página de historial para sesiones Hermes',
|
||||
new_0_5_5_3: 'La página de historial gestiona sesiones de forma independiente',
|
||||
|
||||
@@ -549,6 +549,7 @@ jobTriggered: 'Job declenche',
|
||||
account: 'Compte',
|
||||
agent: 'Agent',
|
||||
memory: 'Memoire',
|
||||
compression: 'Compression',
|
||||
session: 'Session',
|
||||
privacy: 'Confidentialite',
|
||||
apiServer: 'Serveur API',
|
||||
@@ -599,6 +600,18 @@ jobTriggered: 'Job declenche',
|
||||
userCharLimit: 'Limite de caracteres du profil utilisateur',
|
||||
userCharLimitHint: 'Nombre maximum de caracteres pour USER.md',
|
||||
},
|
||||
compression: {
|
||||
enabled: 'Activer la compression',
|
||||
enabledHint: 'Compresser automatiquement un long historique avant de depasser le contexte du modele',
|
||||
threshold: 'Seuil de compression',
|
||||
thresholdHint: 'Demarrer la compression quand les jetons estimes depassent ce ratio de contexte',
|
||||
targetRatio: 'Ratio cible',
|
||||
targetRatioHint: 'Taille cible de l\'historique apres compression comme ratio du contexte',
|
||||
protectLastN: 'Proteger les messages recents',
|
||||
protectLastNHint: 'Garder autant de messages recents non compresses',
|
||||
protectFirstN: 'Proteger les premiers messages',
|
||||
protectFirstNHint: 'Garder autant de premiers messages non compresses',
|
||||
},
|
||||
session: {
|
||||
mode: 'Mode de reinitialisation',
|
||||
modeHint: 'Condition de declenchement de la reinitialisation de session',
|
||||
@@ -952,6 +965,7 @@ jobTriggered: 'Job declenche',
|
||||
new_0_5_30_6: 'Harden Windows compatibility for path detection, file downloads, and job/update subprocesses so they no longer flash terminal windows',
|
||||
new_0_5_30_7: 'Fix config writes and provider presets: validate .env keys, route FUN-Codex through the Responses API, and refresh Z.AI/GLM model lists',
|
||||
new_0_5_30_8: 'Polish frontend details including collapsed sidebar layout, short group labels, sidebar divider, and conversation outline styling',
|
||||
new_0_5_30_9: 'Context compression now follows Profile compression settings and hardens stale snapshots by reusing previous summaries with a safe tail instead of recompressing full history',
|
||||
new_0_5_5_1: '🎉 Joyeuse Fête du Travail! Pas de travail aujourd\'hui, merci de votre compréhension',
|
||||
new_0_5_5_2: 'Ajout d\'une page d\'historique pour les sessions Hermes',
|
||||
new_0_5_5_3: 'La page d\'historique gère les sessions de manière indépendante',
|
||||
|
||||
@@ -549,6 +549,7 @@ export default {
|
||||
account: 'アカウント',
|
||||
agent: 'エージェント',
|
||||
memory: 'メモリ',
|
||||
compression: '圧縮',
|
||||
session: 'セッション',
|
||||
privacy: 'プライバシー',
|
||||
apiServer: 'API サーバー',
|
||||
@@ -599,6 +600,18 @@ export default {
|
||||
userCharLimit: 'ユーザープロファイル文字数上限',
|
||||
userCharLimitHint: 'USER.md の最大文字数',
|
||||
},
|
||||
compression: {
|
||||
enabled: '圧縮を有効化',
|
||||
enabledHint: '長いチャット履歴がモデルコンテキストを超える前に自動圧縮',
|
||||
threshold: '圧縮しきい値',
|
||||
thresholdHint: '推定トークンがこのコンテキスト比率を超えたら圧縮を開始',
|
||||
targetRatio: '目標比率',
|
||||
targetRatioHint: '圧縮後の履歴サイズをコンテキスト比率で指定',
|
||||
protectLastN: '直近メッセージを保護',
|
||||
protectLastNHint: 'この数の最新メッセージは圧縮しない',
|
||||
protectFirstN: '先頭メッセージを保護',
|
||||
protectFirstNHint: 'この数の最初のメッセージは圧縮しない',
|
||||
},
|
||||
session: {
|
||||
mode: 'リセットモード',
|
||||
modeHint: 'セッションリセットのトリガー条件',
|
||||
@@ -953,6 +966,7 @@ export default {
|
||||
new_0_5_30_6: 'Harden Windows compatibility for path detection, file downloads, and job/update subprocesses so they no longer flash terminal windows',
|
||||
new_0_5_30_7: 'Fix config writes and provider presets: validate .env keys, route FUN-Codex through the Responses API, and refresh Z.AI/GLM model lists',
|
||||
new_0_5_30_8: 'Polish frontend details including collapsed sidebar layout, short group labels, sidebar divider, and conversation outline styling',
|
||||
new_0_5_30_9: 'Context compression now follows Profile compression settings and hardens stale snapshots by reusing previous summaries with a safe tail instead of recompressing full history',
|
||||
new_0_5_5_1: '🎉 労働者の日!今日はお休みです、何卒ご理解ください',
|
||||
new_0_5_5_2: 'Hermesセッション履歴ページを追加',
|
||||
new_0_5_5_3: '履歴ページはアクティブチャットに干渉せずにセッション管理',
|
||||
|
||||
@@ -549,6 +549,7 @@ export default {
|
||||
account: '계정',
|
||||
agent: '에이전트',
|
||||
memory: '메모리',
|
||||
compression: '압축',
|
||||
session: '세션',
|
||||
privacy: '개인정보',
|
||||
apiServer: 'API 서버',
|
||||
@@ -599,6 +600,18 @@ export default {
|
||||
userCharLimit: '사용자 프로필 문자 제한',
|
||||
userCharLimitHint: 'USER.md 최대 문자 수',
|
||||
},
|
||||
compression: {
|
||||
enabled: '압축 활성화',
|
||||
enabledHint: '긴 채팅 기록이 모델 컨텍스트를 넘기 전에 자동 압축',
|
||||
threshold: '압축 임계값',
|
||||
thresholdHint: '추정 토큰이 이 컨텍스트 비율을 넘으면 압축 시작',
|
||||
targetRatio: '목표 비율',
|
||||
targetRatioHint: '압축 후 기록 크기를 컨텍스트 비율로 지정',
|
||||
protectLastN: '최근 메시지 보호',
|
||||
protectLastNHint: '이 수만큼 최신 메시지는 압축하지 않음',
|
||||
protectFirstN: '처음 메시지 보호',
|
||||
protectFirstNHint: '이 수만큼 처음 메시지는 압축하지 않음',
|
||||
},
|
||||
session: {
|
||||
mode: '초기화 모드',
|
||||
modeHint: '세션 초기화 트리거 조건',
|
||||
@@ -953,6 +966,7 @@ export default {
|
||||
new_0_5_30_6: 'Harden Windows compatibility for path detection, file downloads, and job/update subprocesses so they no longer flash terminal windows',
|
||||
new_0_5_30_7: 'Fix config writes and provider presets: validate .env keys, route FUN-Codex through the Responses API, and refresh Z.AI/GLM model lists',
|
||||
new_0_5_30_8: 'Polish frontend details including collapsed sidebar layout, short group labels, sidebar divider, and conversation outline styling',
|
||||
new_0_5_30_9: 'Context compression now follows Profile compression settings and hardens stale snapshots by reusing previous summaries with a safe tail instead of recompressing full history',
|
||||
new_0_5_5_1: '🎉 노동절 감사합니다! 오늘은 쉬니까 양해 부탁드립니다',
|
||||
new_0_5_5_2: 'Hermes 세션 기록 페이지 추가',
|
||||
new_0_5_5_3: '기록 페이지는 독립적으로 세션 관리',
|
||||
|
||||
@@ -549,6 +549,7 @@ jobTriggered: 'Job acionado',
|
||||
account: 'Conta',
|
||||
agent: 'Agente',
|
||||
memory: 'Memoria',
|
||||
compression: 'Compressao',
|
||||
session: 'Sessao',
|
||||
privacy: 'Privacidade',
|
||||
apiServer: 'Servidor API',
|
||||
@@ -599,6 +600,18 @@ jobTriggered: 'Job acionado',
|
||||
userCharLimit: 'Limite de caracteres do perfil do usuario',
|
||||
userCharLimitHint: 'Maximo de caracteres para USER.md',
|
||||
},
|
||||
compression: {
|
||||
enabled: 'Ativar compressao',
|
||||
enabledHint: 'Comprimir automaticamente historico longo antes de exceder o contexto do modelo',
|
||||
threshold: 'Limiar de compressao',
|
||||
thresholdHint: 'Iniciar compressao quando tokens estimados excederem esta proporcao do contexto',
|
||||
targetRatio: 'Proporcao alvo',
|
||||
targetRatioHint: 'Tamanho alvo do historico apos compressao como proporcao do contexto',
|
||||
protectLastN: 'Proteger mensagens recentes',
|
||||
protectLastNHint: 'Manter sem compressao esta quantidade de mensagens recentes',
|
||||
protectFirstN: 'Proteger primeiras mensagens',
|
||||
protectFirstNHint: 'Manter sem compressao esta quantidade de mensagens iniciais',
|
||||
},
|
||||
session: {
|
||||
mode: 'Modo de reinicializacao',
|
||||
modeHint: 'Condicao de acionamento para reinicializacao de sessao',
|
||||
@@ -953,6 +966,7 @@ jobTriggered: 'Job acionado',
|
||||
new_0_5_30_6: 'Harden Windows compatibility for path detection, file downloads, and job/update subprocesses so they no longer flash terminal windows',
|
||||
new_0_5_30_7: 'Fix config writes and provider presets: validate .env keys, route FUN-Codex through the Responses API, and refresh Z.AI/GLM model lists',
|
||||
new_0_5_30_8: 'Polish frontend details including collapsed sidebar layout, short group labels, sidebar divider, and conversation outline styling',
|
||||
new_0_5_30_9: 'Context compression now follows Profile compression settings and hardens stale snapshots by reusing previous summaries with a safe tail instead of recompressing full history',
|
||||
new_0_5_5_1: '🎉 Feliz Dia do Trabalhador! Hoje não se trabalha, obrigado pela compreensão',
|
||||
new_0_5_5_2: 'Adicionada página de histórico para sessões Hermes',
|
||||
new_0_5_5_3: 'Página de histórico gerencia sessões de forma independente',
|
||||
|
||||
@@ -696,6 +696,7 @@ export default {
|
||||
account: '帳號',
|
||||
agent: '代理',
|
||||
memory: '記憶',
|
||||
compression: '上下文壓縮',
|
||||
session: '工作階段',
|
||||
privacy: '隱私',
|
||||
apiServer: 'API 伺服器',
|
||||
@@ -754,6 +755,18 @@ export default {
|
||||
userCharLimit: '使用者畫像字元上限',
|
||||
userCharLimitHint: 'USER.md 最大字元數',
|
||||
},
|
||||
compression: {
|
||||
enabled: '啟用壓縮',
|
||||
enabledHint: '長對話接近模型上下文上限前自動壓縮歷史',
|
||||
threshold: '壓縮閾值',
|
||||
thresholdHint: '預估 token 超過上下文比例時開始壓縮',
|
||||
targetRatio: '目標比例',
|
||||
targetRatioHint: '壓縮後歷史保留到上下文的目標比例',
|
||||
protectLastN: '保護最近訊息',
|
||||
protectLastNHint: '最近多少則訊息不參與壓縮',
|
||||
protectFirstN: '保護開頭訊息',
|
||||
protectFirstNHint: '最早多少則訊息不參與壓縮',
|
||||
},
|
||||
session: {
|
||||
mode: '重設模式',
|
||||
modeHint: '工作階段重設的觸發條件',
|
||||
@@ -1243,6 +1256,7 @@ export default {
|
||||
new_0_5_30_6: '優化 Windows 相容性:路徑識別、檔案下載、任務/更新子程序不再彈出額外終端視窗',
|
||||
new_0_5_30_7: '修復配置寫入和 Provider 預設:加強 .env 校驗,FUN-Codex 改走 Responses API,並更新 Z.AI/GLM 模型列表',
|
||||
new_0_5_30_8: '前端體驗細節優化:折疊側邊欄布局、分組短標題、側邊欄分隔線和對話大綱樣式更穩定',
|
||||
new_0_5_30_9: '上下文壓縮現在跟隨 Profile 壓縮配置,並在舊快照失效時複用舊摘要和安全尾部,避免重新壓縮完整歷史',
|
||||
new_0_5_6_1: '新增語音播放功能:使用 Web Speech API,支援手動播放按鈕、自動播放開關、彩虹邊框動畫和行動端最佳化',
|
||||
new_0_5_6_2: '新增強健的 LLM JSON 解析器,相容 Python 格式並從串流事件中擷取文字',
|
||||
new_0_5_6_3: 'Skills 功能增強:使用統計、來源過濾、封存技能、來源追溯和釘選切換',
|
||||
|
||||
@@ -708,6 +708,7 @@ export default {
|
||||
account: '账户',
|
||||
agent: '代理',
|
||||
memory: '记忆',
|
||||
compression: '上下文压缩',
|
||||
session: '会话',
|
||||
privacy: '隐私',
|
||||
apiServer: 'API 服务器',
|
||||
@@ -766,6 +767,18 @@ export default {
|
||||
userCharLimit: '用户画像字符上限',
|
||||
userCharLimitHint: 'USER.md 最大字符数',
|
||||
},
|
||||
compression: {
|
||||
enabled: '启用压缩',
|
||||
enabledHint: '长对话接近模型上下文上限前自动压缩历史',
|
||||
threshold: '压缩阈值',
|
||||
thresholdHint: '预计 token 超过上下文比例时开始压缩',
|
||||
targetRatio: '目标比例',
|
||||
targetRatioHint: '压缩后历史保留到上下文的目标比例',
|
||||
protectLastN: '保护最近消息',
|
||||
protectLastNHint: '最近多少条消息不参与压缩',
|
||||
protectFirstN: '保护开头消息',
|
||||
protectFirstNHint: '最早多少条消息不参与压缩',
|
||||
},
|
||||
session: {
|
||||
mode: '重置模式',
|
||||
modeHint: '会话重置的触发条件',
|
||||
@@ -1253,6 +1266,7 @@ export default {
|
||||
new_0_5_30_6: '优化 Windows 兼容性:路径识别、文件下载、任务/更新子进程不再弹出额外终端窗口',
|
||||
new_0_5_30_7: '修复配置写入和 Provider 预设:加强 .env 校验,FUN-Codex 改走 Responses API,并更新 Z.AI/GLM 模型列表',
|
||||
new_0_5_30_8: '前端体验细节优化:折叠侧边栏布局、分组短标题、侧边栏分隔线和对话大纲样式更稳定',
|
||||
new_0_5_30_9: '上下文压缩现在跟随 Profile 压缩配置,并在旧快照失效时复用旧摘要和安全尾部,避免重新压缩完整历史',
|
||||
|
||||
new_0_5_6_1: '新增语音播放功能:使用 Web Speech API,支持手动播放按钮、自动播放开关、彩虹边框动画和移动端优化',
|
||||
new_0_5_6_2: '新增健壮的 LLM JSON 解析器,兼容 Python 格式并从流式事件中提取文本',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import * as configApi from '@/api/hermes/config'
|
||||
import type { DisplayConfig, AgentConfig, MemoryConfig, SessionResetConfig, PrivacyConfig, ApprovalConfig } from '@/api/hermes/config'
|
||||
import type { DisplayConfig, AgentConfig, MemoryConfig, CompressionConfig, SessionResetConfig, PrivacyConfig, ApprovalConfig } from '@/api/hermes/config'
|
||||
|
||||
export const useSettingsStore = defineStore('settings', () => {
|
||||
const loading = ref(false)
|
||||
@@ -10,6 +10,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
||||
const display = ref<DisplayConfig>({})
|
||||
const agent = ref<AgentConfig>({})
|
||||
const memory = ref<MemoryConfig>({})
|
||||
const compression = ref<CompressionConfig>({})
|
||||
const sessionReset = ref<SessionResetConfig>({})
|
||||
const privacy = ref<PrivacyConfig>({})
|
||||
const approvals = ref<ApprovalConfig>({})
|
||||
@@ -32,6 +33,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
||||
display.value = data.display || {}
|
||||
agent.value = data.agent || {}
|
||||
memory.value = data.memory || {}
|
||||
compression.value = data.compression || {}
|
||||
sessionReset.value = data.session_reset || {}
|
||||
privacy.value = data.privacy || {}
|
||||
approvals.value = data.approvals || {}
|
||||
@@ -58,6 +60,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
||||
case 'display': display.value = { ...display.value, ...values }; break
|
||||
case 'agent': agent.value = { ...agent.value, ...values }; break
|
||||
case 'memory': memory.value = { ...memory.value, ...values }; break
|
||||
case 'compression': compression.value = { ...compression.value, ...values }; break
|
||||
case 'session_reset': sessionReset.value = { ...sessionReset.value, ...values }; break
|
||||
case 'privacy': privacy.value = { ...privacy.value, ...values }; break
|
||||
case 'approvals': approvals.value = { ...approvals.value, ...values }; break
|
||||
@@ -91,6 +94,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
||||
case 'display': display.value = { ...display.value, ...values }; break
|
||||
case 'agent': agent.value = { ...agent.value, ...values }; break
|
||||
case 'memory': memory.value = { ...memory.value, ...values }; break
|
||||
case 'compression': compression.value = { ...compression.value, ...values }; break
|
||||
case 'session_reset': sessionReset.value = { ...sessionReset.value, ...values }; break
|
||||
case 'privacy': privacy.value = { ...privacy.value, ...values }; break
|
||||
case 'approvals': approvals.value = { ...approvals.value, ...values }; break
|
||||
@@ -122,7 +126,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
||||
|
||||
return {
|
||||
loading, saving,
|
||||
display, agent, memory, sessionReset, privacy, approvals,
|
||||
display, agent, memory, compression, sessionReset, privacy, approvals,
|
||||
telegram, discord, slack, whatsapp, matrix, wecom, feishu, dingtalk, qqbot, weixin, platforms,
|
||||
fetchSettings, saveSection, updateLocal,
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useSettingsStore } from "@/stores/hermes/settings";
|
||||
import DisplaySettings from "@/components/hermes/settings/DisplaySettings.vue";
|
||||
import AgentSettings from "@/components/hermes/settings/AgentSettings.vue";
|
||||
import MemorySettings from "@/components/hermes/settings/MemorySettings.vue";
|
||||
import CompressionSettings from "@/components/hermes/settings/CompressionSettings.vue";
|
||||
import SessionSettings from "@/components/hermes/settings/SessionSettings.vue";
|
||||
import PrivacySettings from "@/components/hermes/settings/PrivacySettings.vue";
|
||||
import ModelSettings from "@/components/hermes/settings/ModelSettings.vue";
|
||||
@@ -49,6 +50,9 @@ onMounted(() => {
|
||||
<NTabPane name="memory" :tab="t('settings.tabs.memory')">
|
||||
<MemorySettings />
|
||||
</NTabPane>
|
||||
<NTabPane name="compression" :tab="t('settings.tabs.compression')">
|
||||
<CompressionSettings />
|
||||
</NTabPane>
|
||||
<NTabPane name="session" :tab="t('settings.tabs.session')">
|
||||
<SessionSettings />
|
||||
</NTabPane>
|
||||
|
||||
Reference in New Issue
Block a user