import { useTranslation } from 'react-i18next'; import { HelpText } from './HelpText'; import { FieldLabel, FieldInput } from './formUtils'; import type { SectionFormProps } from './types'; /** * Reflection (Hermes mode) settings. * * Toggle + caps for the per-job reflection loop that auto-updates a user's * persistent memory. See `src/engine/reflection/` and the design doc at * docs/superpowers/specs/2026-05-11-self-improving-memory-design.md. * * For Reflection to actually run, a worker with `roles: [reflection]` must * exist in the LLM Workers tab. Otherwise (with the default `worker_required`) * jobs are silently skipped. */ export function ReflectionForm({ config, onChange }: SectionFormProps) { const { t } = useTranslation('settings'); const reflection = config.reflection ?? {}; // Step 7 (design 2026-05-21): read v2 `llm.workers`. The v2 API contract // already strips the legacy `provider` block from GET /api/config, so // falling back to it would always be empty. Kept as a defensive `?? []` // for the brief window where draft state may still be undefined. const workers = config.llm?.workers ?? []; const hasReflectionWorker = workers.some( (w: { roles?: string[] }) => Array.isArray(w.roles) && w.roles.includes('reflection'), ); const enabled = reflection.enabled === true; return (

Reflection (Hermes mode)

{t('reflection.intro')}

{t('reflection.enableHelp')}
{enabled && !hasReflectionWorker && (
{t('reflection.workerWarn.title')}
{t('reflection.workerWarn.body')}
{t('reflection.workerWarn.snippet')}
)}
{t('reflection.workerRequiredHelp')}

Caps

Max memory changes per job onChange('reflection.maxMemoryChangesPerJob', Number(v))} /> {t('reflection.maxMemHelp')}
Max entry body bytes onChange('reflection.maxEntryBodyBytes', Number(v))} /> {t('reflection.maxBodyHelp')}
Piece edit cooldown (hours) onChange('reflection.pieceEditCooldownHours', Number(v))} /> {t('reflection.cooldownHelp')}
Activity log max bytes onChange('reflection.activityLogMaxBytes', Number(v))} /> {t('reflection.activityLogHelp')}

Budget

Per-user daily budget (tokens) onChange('reflection.perUserDailyBudgetTokens', Number(v))} /> {t('reflection.dailyBudgetHelp')}

Snapshot & Retention

Snapshot retention (days) onChange('reflection.snapshotRetentionDays', Number(v))} /> {t('reflection.snapRetentionHelp')}
Snapshot max bytes per user onChange('reflection.snapshotMaxBytesPerUser', Number(v))} /> {t('reflection.snapMaxUserHelp')}
Snapshot max bytes per entry onChange('reflection.snapshotMaxBytesPerEntry', Number(v))} /> {t('reflection.snapMaxEntryHelp')}
{t('reflection.storeLlmRawHelp')}

Monitoring

Abstain rate floor onChange('reflection.abstainRateFloor', v ? Number(v) : undefined)} /> {t('reflection.abstainFloorHelp')}
); }