feat(dashboard): expose build timeout & insight extraction settings in the UI (#1935)
### Problem Two settings that already exist in the `Settings` schema and are honored by the engine have **no control anywhere in the dashboard UI**: - `buildTimeoutMs` — max time for build/verification commands (default `300000` = 5 min) - `insightExtractionEnabled` (+ `insightExtractionSchedule`) — periodic extraction of durable insights from completed tasks into memory Because there's no UI, the only way to change them is to hand-edit `config.json` — but that has to be done with the app fully closed, since the running app rewrites `config.json` from its database on reload/shutdown and silently clobbers live file edits. That's a confusing footgun (edits appear to "not stick"), and 5 minutes is too low a build timeout for large monorepo / Docker builds. ### Change Expose both via controls that mirror the existing patterns in the same sections — no schema, route, or persistence changes needed (the keys already flow through `form`/`setForm` → `updateSettings`). - **Scheduling section:** "Build/Verification Timeout (minutes)", placed next to the existing "Stuck Task Timeout (minutes)", using the same minutes↔ms conversion. - **Memory section:** "Enable Insight Extraction" checkbox + conditional cron "Schedule" field, placed next to the existing Auto-Summarize controls (matching how `insightExtractionSchedule` is already documented in `types.ts`). Both use the existing `t(...)` i18n fallback style used throughout these sections. ### Scope note (feedback welcome) Both live in their existing **project-scoped** sections (Scheduling, Memory), which is the natural home. If maintainers want these settable as **global/user defaults** too, I'm happy to add a global-defaults counterpart in a follow-up — just wanted to keep this PR focused and non-duplicative. ### Testing - Both keys are pre-existing fields on the `Settings` type (`buildTimeoutMs?: number` at `packages/core/src/types.ts`; `insightExtractionEnabled?`/`insightExtractionSchedule?` likewise), so the additions are type-safe. - Controls follow the exact JSX/handler pattern of adjacent fields already in each section. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added an **Insight Extraction** option in memory settings, including an enable/disable toggle and a schedule field that appears when enabled. * Added a **Build/Verification Timeout** setting in scheduling, with minute-based input and helpful guidance text. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -112,6 +112,19 @@ export function MemorySection({ scopeBanner, form, setForm, memory }: MemorySect
|
||||
</div>
|
||||
</>)}
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="insightExtractionEnabled" className="checkbox-label">
|
||||
<input id="insightExtractionEnabled" type="checkbox" checked={form.insightExtractionEnabled || false} onChange={(e) => setForm((f) => ({ ...f, insightExtractionEnabled: e.target.checked }))}/>{t("settings.memory.enableInsightExtraction", " Enable Insight Extraction ")}</label>
|
||||
<small>{t("settings.memory.periodicallyExtractDurableInsightsFromCompletedTasks", "Periodically extract durable insights/learnings from completed tasks into memory")}</small>
|
||||
</div>
|
||||
|
||||
{(form.insightExtractionEnabled || false) && (
|
||||
<div className="form-group">
|
||||
<label htmlFor="insightExtractionSchedule">{t("settings.memory.scheduleCron", "Schedule (cron)")}</label>
|
||||
<input id="insightExtractionSchedule" type="text" className="input" value={form.insightExtractionSchedule ?? "0 2 * * *"} onChange={(e) => setForm((f) => ({ ...f, insightExtractionSchedule: e.target.value }))} placeholder={t("settings.memory.02", "0 2 * * *")}/>
|
||||
<small>{t("settings.memory.cronExpressionForInsightExtractionScheduleDefaultDaily", "Cron expression for insight extraction schedule (default: daily at 2 AM)")}</small>
|
||||
</div>)}
|
||||
|
||||
<div style={{ borderTop: "1px solid var(--border)", margin: "var(--space-lg) 0" }}/>
|
||||
|
||||
<div className="form-group">
|
||||
|
||||
@@ -108,6 +108,15 @@ export function SchedulingSection({ scopeBanner, form, setForm, globalMaxConcurr
|
||||
}}/>
|
||||
<small>{t("settings.scheduling.timeoutInMinutesForDetectingStuckTasksWhen", "Timeout in minutes for detecting stuck tasks. When a task's agent session shows no activity for longer than this duration, the task is terminated and retried. Leave empty to disable. Suggested: 10. Default: 10 minutes (600000ms).")}</small>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="buildTimeoutMs">{t("settings.scheduling.buildTimeoutMinutes", "Build/Verification Timeout (minutes)")}</label>
|
||||
<input id="buildTimeoutMs" type="number" min={1} step={1} value={form.buildTimeoutMs ? Math.round(form.buildTimeoutMs / 60000) : ""} onChange={(e) => {
|
||||
const val = e.target.value;
|
||||
const num = Number(val);
|
||||
setForm((f) => ({ ...f, buildTimeoutMs: val && num > 0 ? num * 60000 : undefined }));
|
||||
}}/>
|
||||
<small>{t("settings.scheduling.maximumTimeInMinutesForBuildVerificationCommands", "Maximum time in minutes for build/verification commands before they are killed. Raise for large monorepo or Docker builds. Default: 5.")}</small>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="staleHighFanoutBlockerAgeThresholdMs">{t("settings.scheduling.staleHighFanOutEscalationHours", "Stale High Fan-out Escalation (hours)")}</label>
|
||||
<input id="staleHighFanoutBlockerAgeThresholdMs" type="number" min={1} step={1} value={form.staleHighFanoutBlockerAgeThresholdMs ? Math.round(form.staleHighFanoutBlockerAgeThresholdMs / 3600000) : ""} onChange={(e) => {
|
||||
|
||||
Reference in New Issue
Block a user