feat(FN-1808): merge fusion/fn-1808
This commit is contained in:
@@ -107,7 +107,7 @@ export function SettingsModal({
|
||||
onColorThemeChange,
|
||||
onReopenOnboarding,
|
||||
}: SettingsModalProps) {
|
||||
const [form, setForm] = useState<Settings & { worktreeInitCommand?: string }>({ maxConcurrent: 2, maxWorktrees: 4, pollIntervalMs: 15000, groupOverlappingFiles: true, autoMerge: true, mergeStrategy: "direct", recycleWorktrees: false, worktreeNaming: "random", includeTaskIdInCommit: true, worktreeInitCommand: "", ntfyEnabled: false, ntfyTopic: undefined });
|
||||
const [form, setForm] = useState<Settings & { worktreeInitCommand?: string }>({ maxConcurrent: 2, maxTriageConcurrent: 2, maxWorktrees: 4, pollIntervalMs: 15000, groupOverlappingFiles: true, autoMerge: true, mergeStrategy: "direct", recycleWorktrees: false, worktreeNaming: "random", includeTaskIdInCommit: true, worktreeInitCommand: "", ntfyEnabled: false, ntfyTopic: undefined });
|
||||
const [loading, setLoading] = useState(true);
|
||||
// Track initial values to detect explicit clears for null-as-delete semantics
|
||||
const [initialValues, setInitialValues] = useState<Settings | null>(null);
|
||||
@@ -1568,6 +1568,21 @@ export function SettingsModal({
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="maxTriageConcurrent">Max Triage Concurrent</label>
|
||||
<input
|
||||
id="maxTriageConcurrent"
|
||||
type="number"
|
||||
min={1}
|
||||
max={10}
|
||||
value={form.maxTriageConcurrent ?? ""}
|
||||
onChange={(e) => {
|
||||
const val = e.target.value;
|
||||
setForm((f) => ({ ...f, maxTriageConcurrent: val === "" ? undefined : Number(val) } as any));
|
||||
}}
|
||||
/>
|
||||
<small>Maximum concurrent triage/specification agents</small>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="pollIntervalMs">Poll Interval (ms)</label>
|
||||
<input
|
||||
|
||||
@@ -7,6 +7,7 @@ import type { Settings, ThemeMode, ColorTheme } from "@fusion/core";
|
||||
|
||||
const defaultSettings: Settings = {
|
||||
maxConcurrent: 2,
|
||||
maxTriageConcurrent: 2,
|
||||
maxWorktrees: 4,
|
||||
pollIntervalMs: 15000,
|
||||
groupOverlappingFiles: false,
|
||||
|
||||
@@ -2208,19 +2208,20 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
|
||||
});
|
||||
};
|
||||
|
||||
// Scheduler config (includes persisted settings — only needs maxConcurrent/maxWorktrees)
|
||||
// Scheduler config (includes persisted settings — only needs maxConcurrent/maxTriageConcurrent/maxWorktrees)
|
||||
router.get("/config", async (req, res) => {
|
||||
try {
|
||||
const { store: scopedStore } = await getProjectContext(req);
|
||||
const settings = await scopedStore.getSettingsFast();
|
||||
res.json({
|
||||
maxConcurrent: settings.maxConcurrent ?? options?.maxConcurrent ?? 2,
|
||||
maxTriageConcurrent: settings.maxTriageConcurrent ?? settings.maxConcurrent ?? 2,
|
||||
maxWorktrees: settings.maxWorktrees ?? 4,
|
||||
rootDir: scopedStore.getRootDir(),
|
||||
});
|
||||
} catch {
|
||||
const { store: scopedStore } = await getProjectContext(req);
|
||||
res.json({ maxConcurrent: options?.maxConcurrent ?? 2, maxWorktrees: 4, rootDir: scopedStore.getRootDir() });
|
||||
res.json({ maxConcurrent: options?.maxConcurrent ?? 2, maxTriageConcurrent: options?.maxConcurrent ?? 2, maxWorktrees: 4, rootDir: scopedStore.getRootDir() });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user