Expose settings defaults directly in dashboard help text so operators can see baseline values while editing settings. - Add default-value wording across global and project settings descriptions and locale strings. - Document the dashboard/default-reference alignment and add a changeset for the published CLI package. - Add coverage that every visible settings field includes its default in helper text and update existing assertions. Files changed: .changeset/fn-7505-settings-default-descriptions.md | 7 + docs/dashboard-guide.md | 3 + docs/settings-reference.md | 3 + .../__tests__/SettingsModal.general.test.tsx | 2 +- .../settings/sections/AgentPermissionsSection.tsx | 4 +- .../settings/sections/AppearanceSection.tsx | 4 +- .../settings/sections/BackupsSection.tsx | 13 +- .../settings/sections/CommandsSection.tsx | 4 +- .../settings/sections/ExperimentalSection.tsx | 2 +- .../settings/sections/GeneralSection.tsx | 26 +- .../settings/sections/GlobalGeneralSection.tsx | 25 +- .../settings/sections/GlobalModelsSection.tsx | 24 +- .../settings/sections/McpServersCard.tsx | 1 + .../components/settings/sections/MemorySection.tsx | 12 +- .../components/settings/sections/MergeSection.tsx | 37 +- .../settings/sections/ModelPricingSection.tsx | 2 +- .../settings/sections/NodeRoutingSection.tsx | 3 +- .../settings/sections/NodeSyncSection.tsx | 6 +- .../settings/sections/NotificationsSection.tsx | 14 +- .../settings/sections/ProjectModelsSection.tsx | 11 +- .../settings/sections/PromptsSection.tsx | 2 +- .../components/settings/sections/RemoteSection.tsx | 7 +- .../settings/sections/ResearchGlobalSection.tsx | 15 +- .../settings/sections/ResearchProjectSection.tsx | 16 +- .../settings/sections/ScheduledEvalsSection.tsx | 7 +- .../settings/sections/SchedulingSection.tsx | 20 +- .../settings/sections/WorktreesSection.tsx | 14 +- .../sections/__tests__/AppearanceSection.test.tsx | 4 +- .../MergeSection.legacy-automerge-cleanup.test.tsx | 2 +- .../settings-default-descriptions.test.tsx | 573 +++++++++++++++++++++ packages/i18n/locales/en/app.json | 261 ++++++---- 31 files changed, 914 insertions(+), 210 deletions(-) Fusion-Task-Id: FN-7505 Fusion-Task-Lineage: 7688caf2-2a95-4401-8b27-9da4b46ecfcd Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
118 lines
6.9 KiB
TypeScript
118 lines
6.9 KiB
TypeScript
import type { ReactNode } from "react";
|
|
import type { SectionBaseProps } from "./context";
|
|
import { useTranslation } from "react-i18next";
|
|
export interface ResearchProjectSectionProps extends SectionBaseProps {
|
|
scopeBanner: ReactNode;
|
|
researchLimitError: string | null;
|
|
}
|
|
export function ResearchProjectSection({ scopeBanner, form, setForm, researchLimitError }: ResearchProjectSectionProps) {
|
|
const { t } = useTranslation("app");
|
|
const limits = form.researchSettings?.limits;
|
|
const sources = form.researchSettings?.enabledSources;
|
|
return (<>
|
|
{scopeBanner}
|
|
<h4 className="settings-section-heading">{t("settings.researchProject.projectResearchSettings", "Project Research Settings")}</h4>
|
|
<div className="form-group">
|
|
<label htmlFor="research-project-enabled" className="checkbox-label">
|
|
<input id="research-project-enabled" type="checkbox" checked={form.researchSettings?.enabled ?? true} onChange={(event) => setForm((current) => ({
|
|
...current,
|
|
researchSettings: {
|
|
...(current.researchSettings ?? {}),
|
|
enabled: event.target.checked,
|
|
},
|
|
}))}/>{t("settings.researchProject.enableResearchInThisProject", " Enable research in this project ")}</label>
|
|
<small>{t("settings.researchProject.enableResearchInThisProjectHint", "Default: enabled.")}</small>
|
|
</div>
|
|
<div className="form-group">
|
|
<label>{t("settings.researchProject.enabledSources", "Enabled Sources")}</label>
|
|
<label htmlFor="research-project-source-webSearch" className="checkbox-label settings-research-source-locked">
|
|
<input id="research-project-source-webSearch" type="checkbox" checked disabled readOnly/>{t("settings.researchProject.webSearch", " Web Search ")}<span className="settings-muted">{t("settings.researchProject.alwaysOn", "Always on")}</span>
|
|
</label>
|
|
<small className="settings-muted">{t("settings.researchProject.webSearchIsAlwaysEnabledConfigureTheSearch", " Web search is always enabled. Configure the search provider under Research Defaults. ")}</small>
|
|
<div className="settings-research-source-grid">
|
|
{[
|
|
["pageFetch", t("settings.researchProject.pageFetch", "Page Fetch"), "Default: enabled."],
|
|
["github", t("settings.researchProject.github", "GitHub"), "Default: disabled."],
|
|
["localDocs", t("settings.researchProject.localDocs", "Local Docs"), "Default: enabled."],
|
|
["llmSynthesis", t("settings.researchProject.llmSynthesis", "LLM Synthesis"), "Default: enabled."],
|
|
].map(([key, label, defaultHint]) => (<label key={key} htmlFor={`research-project-source-${key}`} className="checkbox-label">
|
|
<input id={`research-project-source-${key}`} type="checkbox" checked={sources?.[key as keyof NonNullable<typeof sources>] ?? false} onChange={(event) => setForm((current) => ({
|
|
...current,
|
|
researchSettings: {
|
|
...(current.researchSettings ?? {}),
|
|
enabledSources: {
|
|
...(current.researchSettings?.enabledSources ?? {}),
|
|
[key]: event.target.checked,
|
|
},
|
|
},
|
|
}))}/>
|
|
{label}
|
|
<small>{defaultHint}</small>
|
|
</label>))}
|
|
</div>
|
|
</div>
|
|
<div className="form-group">
|
|
<div className="settings-research-limits-grid">
|
|
<div className="settings-research-limit-field">
|
|
<label htmlFor="research-project-max-concurrent">{t("settings.researchProject.maxConcurrentRuns", "Max Concurrent Runs")}</label>
|
|
<input id="research-project-max-concurrent" className="input" type="number" min={1} value={limits?.maxConcurrentRuns ?? 3} onChange={(event) => setForm((current) => ({
|
|
...current,
|
|
researchSettings: {
|
|
...(current.researchSettings ?? {}),
|
|
limits: {
|
|
...(current.researchSettings?.limits ?? {}),
|
|
maxConcurrentRuns: event.target.value === "" ? undefined : Number(event.target.value),
|
|
},
|
|
},
|
|
}))}/>
|
|
<small>{t("settings.researchProject.maxConcurrentRunsHint", "Default: 3.")}</small>
|
|
</div>
|
|
<div className="settings-research-limit-field">
|
|
<label htmlFor="research-project-max-sources">{t("settings.researchProject.maxSourcesPerRun", "Max Sources Per Run")}</label>
|
|
<input id="research-project-max-sources" className="input" type="number" min={1} value={limits?.maxSourcesPerRun ?? 20} onChange={(event) => setForm((current) => ({
|
|
...current,
|
|
researchSettings: {
|
|
...(current.researchSettings ?? {}),
|
|
limits: {
|
|
...(current.researchSettings?.limits ?? {}),
|
|
maxSourcesPerRun: event.target.value === "" ? undefined : Number(event.target.value),
|
|
},
|
|
},
|
|
}))}/>
|
|
<small>{t("settings.researchProject.maxSourcesPerRunHint", "Default: 20.")}</small>
|
|
</div>
|
|
<div className="settings-research-limit-field">
|
|
<label htmlFor="research-project-max-duration">{t("settings.researchProject.maxDurationMs", "Max Duration (ms)")}</label>
|
|
<input id="research-project-max-duration" className="input" type="number" min={1000} value={limits?.maxDurationMs ?? 300000} onChange={(event) => setForm((current) => ({
|
|
...current,
|
|
researchSettings: {
|
|
...(current.researchSettings ?? {}),
|
|
limits: {
|
|
...(current.researchSettings?.limits ?? {}),
|
|
maxDurationMs: event.target.value === "" ? undefined : Number(event.target.value),
|
|
},
|
|
},
|
|
}))}/>
|
|
<small>{t("settings.researchProject.maxDurationMsHint", "Default: 300000 (5 minutes).")}</small>
|
|
</div>
|
|
<div className="settings-research-limit-field">
|
|
<label htmlFor="research-project-request-timeout">{t("settings.researchProject.requestTimeoutMs", "Request Timeout (ms)")}</label>
|
|
<input id="research-project-request-timeout" className="input" type="number" min={1000} value={limits?.requestTimeoutMs ?? 30000} onChange={(event) => setForm((current) => ({
|
|
...current,
|
|
researchSettings: {
|
|
...(current.researchSettings ?? {}),
|
|
limits: {
|
|
...(current.researchSettings?.limits ?? {}),
|
|
requestTimeoutMs: event.target.value === "" ? undefined : Number(event.target.value),
|
|
},
|
|
},
|
|
}))}/>
|
|
<small>{t("settings.researchProject.requestTimeoutMsHint", "Default: 30000 (30 seconds).")}</small>
|
|
</div>
|
|
{researchLimitError && <small className="field-error settings-research-limits-error">{researchLimitError}</small>}
|
|
</div>
|
|
</div>
|
|
</>);
|
|
}
|
|
export default ResearchProjectSection;
|