feat(FN-3313): add plugin slot registry, planning mode rewind, and docker n

This merge lands five features spanning the Fusion stack: research settings key renaming (FN-3313, Steps 2–7) across types, defaults, CLI, and engine packages; static plugin slot-host rendering contract documentation (FN-3260); Docker node provisioning routes with a planning modal (FN-3116); plannin

Fusion-Task-Id: FN-3313
This commit is contained in:
Fusion
2026-05-04 20:14:46 -07:00
committed by gsxdsm
parent f5268019f9
commit a02b42106d
16 changed files with 118 additions and 90 deletions

View File

@@ -96,7 +96,7 @@ describe("resolveResearchSettings", () => {
it("falls back through legacy and hardcoded limit chains", () => {
const fromLegacyProjectTimeout = resolveResearchSettings({
researchDefaultTimeout: 111_000,
researchFetchTimeoutMs: 8_000,
researchGlobalFetchTimeoutMs: 8_000,
});
expect(fromLegacyProjectTimeout.limits.maxDurationMs).toBe(111_000);
expect(fromLegacyProjectTimeout.limits.requestTimeoutMs).toBe(8_000);

View File

@@ -98,6 +98,29 @@ describe("settings key parity", () => {
// ── Model Lane Key Parity Regression Tests (FN-1729) ────────────────────────
describe("research global key parity regression (FN-3313)", () => {
const globalResearchFlatKeys = [
"researchGlobalWebSearchProvider",
"researchGlobalSearxngUrl",
"researchGlobalBraveApiKey",
"researchGlobalGoogleSearchApiKey",
"researchGlobalGoogleSearchCx",
"researchGlobalTavilyApiKey",
"researchGlobalGitHubEnabled",
"researchGlobalLocalDocsEnabled",
"researchGlobalMaxSearchResults",
"researchGlobalFetchTimeoutMs",
"researchGlobalUserAgent",
] as const;
it.each(globalResearchFlatKeys)("%s is global-scoped only", (key) => {
expect(isGlobalSettingsKey(key)).toBe(true);
expect(isProjectSettingsKey(key)).toBe(false);
});
});
// ── Model Lane Key Parity Regression Tests (FN-1729) ────────────────────────
describe("model lane key parity regression (FN-1729)", () => {
// All model lane provider/modelId pairs that should exist
const allModelLanePairs = [

View File

@@ -58,7 +58,7 @@ export function resolveResearchSettings(settings: Partial<Settings> | undefined)
maxConcurrentRuns: projectSettings?.limits?.maxConcurrentRuns ?? settings?.researchMaxConcurrentRuns ?? settings?.researchGlobalMaxConcurrentRuns ?? 3,
maxSourcesPerRun: projectSettings?.limits?.maxSourcesPerRun ?? globalDefaults?.maxSourcesPerRun ?? settings?.researchMaxSourcesPerRun ?? settings?.researchGlobalMaxSourcesPerRun ?? 20,
maxDurationMs: projectSettings?.limits?.maxDurationMs ?? settings?.researchDefaultTimeout ?? settings?.researchGlobalDefaultTimeout ?? 300000,
requestTimeoutMs: projectSettings?.limits?.requestTimeoutMs ?? settings?.researchFetchTimeoutMs ?? 30000,
requestTimeoutMs: projectSettings?.limits?.requestTimeoutMs ?? settings?.researchGlobalFetchTimeoutMs ?? 30000,
},
defaultExportFormat: globalDefaults?.defaultExportFormat ?? "markdown",
};

View File

@@ -100,17 +100,17 @@ export const DEFAULT_GLOBAL_SETTINGS = {
researchGlobalDefaultTimeout: 300000,
researchGlobalMaxSourcesPerRun: 20,
researchGlobalMaxSynthesisRounds: 2,
researchWebSearchProvider: "none",
researchSearxngUrl: undefined,
researchBraveApiKey: undefined,
researchGoogleSearchApiKey: undefined,
researchGoogleSearchCx: undefined,
researchTavilyApiKey: undefined,
researchGitHubEnabled: false,
researchLocalDocsEnabled: true,
researchMaxSearchResults: 10,
researchFetchTimeoutMs: 30_000,
researchUserAgent: "FusionResearchBot/1.0",
researchGlobalWebSearchProvider: "none",
researchGlobalSearxngUrl: undefined,
researchGlobalBraveApiKey: undefined,
researchGlobalGoogleSearchApiKey: undefined,
researchGlobalGoogleSearchCx: undefined,
researchGlobalTavilyApiKey: undefined,
researchGlobalGitHubEnabled: false,
researchGlobalLocalDocsEnabled: true,
researchGlobalMaxSearchResults: 10,
researchGlobalFetchTimeoutMs: 30_000,
researchGlobalUserAgent: "FusionResearchBot/1.0",
remoteAccess: {
activeProvider: null,
providers: {

View File

@@ -1519,27 +1519,27 @@ export interface GlobalSettings {
* Default: 2. */
researchGlobalMaxSynthesisRounds?: number;
/** Web search backend for auto-research. Default: "none" (disabled). */
researchWebSearchProvider?: WebSearchBackend;
/** SearXNG instance URL (required when researchWebSearchProvider is "searxng"). */
researchSearxngUrl?: string;
/** Brave Search API key (required when researchWebSearchProvider is "brave"). */
researchBraveApiKey?: string;
/** Google Custom Search API key (required when researchWebSearchProvider is "google"). */
researchGoogleSearchApiKey?: string;
/** Google Custom Search engine ID (required when researchWebSearchProvider is "google"). */
researchGoogleSearchCx?: string;
/** Tavily API key (required when researchWebSearchProvider is "tavily"). */
researchTavilyApiKey?: string;
researchGlobalWebSearchProvider?: WebSearchBackend;
/** SearXNG instance URL (required when researchGlobalWebSearchProvider is "searxng"). */
researchGlobalSearxngUrl?: string;
/** Brave Search API key (required when researchGlobalWebSearchProvider is "brave"). */
researchGlobalBraveApiKey?: string;
/** Google Custom Search API key (required when researchGlobalWebSearchProvider is "google"). */
researchGlobalGoogleSearchApiKey?: string;
/** Google Custom Search engine ID (required when researchGlobalWebSearchProvider is "google"). */
researchGlobalGoogleSearchCx?: string;
/** Tavily API key (required when researchGlobalWebSearchProvider is "tavily"). */
researchGlobalTavilyApiKey?: string;
/** Enable GitHub repository/issue search provider. Default: false. */
researchGitHubEnabled?: boolean;
researchGlobalGitHubEnabled?: boolean;
/** Enable local project documentation search provider. Default: true. */
researchLocalDocsEnabled?: boolean;
researchGlobalLocalDocsEnabled?: boolean;
/** Maximum search results per provider query. Default: 10. */
researchMaxSearchResults?: number;
researchGlobalMaxSearchResults?: number;
/** HTTP fetch timeout in milliseconds for page/content fetching. Default: 30000. */
researchFetchTimeoutMs?: number;
researchGlobalFetchTimeoutMs?: number;
/** User-Agent header for HTTP requests made by research providers. Default: "FusionResearchBot/1.0". */
researchUserAgent?: string;
researchGlobalUserAgent?: string;
/** Global-scoped remote access configuration persisted in `~/.fusion/settings.json`.
* Stores both provider configs, active provider selection, token strategy,
* and lifecycle restart metadata for remote tunnel orchestration. */