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:
@@ -122,13 +122,13 @@ async function enableResearch(cwd: string): Promise<TaskStore> {
|
||||
await store.updateGlobalSettings({
|
||||
researchGlobalEnabled: true,
|
||||
researchGlobalDefaults: { searchProvider: "searxng" },
|
||||
researchSearxngUrl: "http://localhost:8888",
|
||||
researchGlobalSearxngUrl: "http://localhost:8888",
|
||||
});
|
||||
await store.updateSettings({
|
||||
researchEnabled: true,
|
||||
researchSettings: { enabled: true, searchProvider: "searxng" },
|
||||
researchWebSearchProvider: "searxng",
|
||||
researchSearxngUrl: "http://localhost:8888",
|
||||
researchGlobalWebSearchProvider: "searxng",
|
||||
researchGlobalSearxngUrl: "http://localhost:8888",
|
||||
});
|
||||
return store;
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ describe("research extension tools", () => {
|
||||
const store = new TaskStore(tmpDir);
|
||||
await store.init();
|
||||
await store.updateSettings({
|
||||
researchWebSearchProvider: "tavily",
|
||||
researchGlobalWebSearchProvider: "tavily",
|
||||
researchSettings: { enabled: true },
|
||||
researchGlobalDefaults: { searchProvider: "tavily" },
|
||||
});
|
||||
@@ -88,8 +88,8 @@ describe("research extension tools", () => {
|
||||
const store = new TaskStore(tmpDir);
|
||||
await store.init();
|
||||
await store.updateSettings({
|
||||
researchWebSearchProvider: "tavily",
|
||||
researchTavilyApiKey: "test-key",
|
||||
researchGlobalWebSearchProvider: "tavily",
|
||||
researchGlobalTavilyApiKey: "test-key",
|
||||
researchSettings: { enabled: true },
|
||||
researchGlobalDefaults: { searchProvider: "tavily" },
|
||||
});
|
||||
@@ -117,8 +117,8 @@ describe("research extension tools", () => {
|
||||
const store = new TaskStore(tmpDir);
|
||||
await store.init();
|
||||
await store.updateSettings({
|
||||
researchWebSearchProvider: "tavily",
|
||||
researchTavilyApiKey: "test-key",
|
||||
researchGlobalWebSearchProvider: "tavily",
|
||||
researchGlobalTavilyApiKey: "test-key",
|
||||
researchSettings: { enabled: true },
|
||||
researchGlobalDefaults: { searchProvider: "tavily" },
|
||||
});
|
||||
|
||||
@@ -22,7 +22,7 @@ const researchStoreMock = {
|
||||
|
||||
const storeMock = {
|
||||
init: vi.fn(),
|
||||
getSettings: vi.fn(async () => ({ researchSettings: { enabled: true }, researchWebSearchProvider: "tavily", researchTavilyApiKey: "x" })),
|
||||
getSettings: vi.fn(async () => ({ researchSettings: { enabled: true }, researchGlobalWebSearchProvider: "tavily", researchGlobalTavilyApiKey: "x" })),
|
||||
getResearchStore: vi.fn(() => researchStoreMock),
|
||||
};
|
||||
|
||||
@@ -145,7 +145,7 @@ describe("research commands", () => {
|
||||
});
|
||||
|
||||
it("errors when provider credentials are missing", async () => {
|
||||
storeMock.getSettings.mockResolvedValueOnce({ researchSettings: { enabled: true }, researchWebSearchProvider: "tavily" });
|
||||
storeMock.getSettings.mockResolvedValueOnce({ researchSettings: { enabled: true }, researchGlobalWebSearchProvider: "tavily" });
|
||||
await expect(runResearchCreate({ query: "hello" })).rejects.toThrow("process.exit:1");
|
||||
expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining("missing-credentials"));
|
||||
});
|
||||
|
||||
@@ -43,10 +43,10 @@ async function getStore(projectName?: string): Promise<TaskStore> {
|
||||
|
||||
function hasProviderCredentials(settings: Awaited<ReturnType<TaskStore["getSettings"]>>, providerId: string | undefined): boolean {
|
||||
if (!providerId) return false;
|
||||
if (providerId === "searxng") return Boolean(settings.researchSearxngUrl);
|
||||
if (providerId === "brave") return Boolean(settings.researchBraveApiKey);
|
||||
if (providerId === "google") return Boolean(settings.researchGoogleSearchApiKey && settings.researchGoogleSearchCx);
|
||||
if (providerId === "tavily") return Boolean(settings.researchTavilyApiKey);
|
||||
if (providerId === "searxng") return Boolean(settings.researchGlobalSearxngUrl);
|
||||
if (providerId === "brave") return Boolean(settings.researchGlobalBraveApiKey);
|
||||
if (providerId === "google") return Boolean(settings.researchGlobalGoogleSearchApiKey && settings.researchGlobalGoogleSearchCx);
|
||||
if (providerId === "tavily") return Boolean(settings.researchGlobalTavilyApiKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ async function getResearchRuntime(store: TaskStore) {
|
||||
throw new Error("feature-disabled: Research is disabled in settings.");
|
||||
}
|
||||
|
||||
const configuredProvider = (resolved.searchProvider as string | undefined) ?? settings.researchWebSearchProvider;
|
||||
const configuredProvider = (resolved.searchProvider as string | undefined) ?? settings.researchGlobalWebSearchProvider;
|
||||
if (!configuredProvider) {
|
||||
throw new Error("provider-unavailable: Research providers are not configured. Add provider credentials in settings.");
|
||||
}
|
||||
|
||||
@@ -139,15 +139,15 @@ async function getResearchAvailability(store: TaskStore): Promise<{ ok: boolean;
|
||||
return { ok: false, code: "feature-disabled", message: "Research is disabled in settings." };
|
||||
}
|
||||
|
||||
const backend = (resolved.searchProvider as string | undefined) ?? settings.researchWebSearchProvider;
|
||||
const backend = (resolved.searchProvider as string | undefined) ?? settings.researchGlobalWebSearchProvider;
|
||||
const configured = backend === "searxng"
|
||||
? Boolean(settings.researchSearxngUrl)
|
||||
? Boolean(settings.researchGlobalSearxngUrl)
|
||||
: backend === "brave"
|
||||
? Boolean(settings.researchBraveApiKey)
|
||||
? Boolean(settings.researchGlobalBraveApiKey)
|
||||
: backend === "google"
|
||||
? Boolean(settings.researchGoogleSearchApiKey && settings.researchGoogleSearchCx)
|
||||
? Boolean(settings.researchGlobalGoogleSearchApiKey && settings.researchGlobalGoogleSearchCx)
|
||||
: backend === "tavily"
|
||||
? Boolean(settings.researchTavilyApiKey)
|
||||
? Boolean(settings.researchGlobalTavilyApiKey)
|
||||
: false;
|
||||
|
||||
if (!backend) {
|
||||
|
||||
Reference in New Issue
Block a user