fix(mi,canvas): filter disabled modules from MI assistant and eliminate app-switcher flash
MI now loads space doc to filter module list, capabilities, and fallback by enabledModules. Canvas fetches /api/modules and space modules in parallel via Promise.all, calling setModules once with filtered list. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ac028cbe04
commit
8d4e1fd0ff
|
|
@ -13,6 +13,7 @@ import type { MiMessage } from "./mi-provider";
|
|||
import { getModuleInfoList, getAllModules } from "../shared/module";
|
||||
import { resolveCallerRole, roleAtLeast } from "./spaces";
|
||||
import type { SpaceRoleString } from "./spaces";
|
||||
import { loadCommunity, getDocumentData } from "./community-store";
|
||||
import { verifyToken, extractToken } from "./auth";
|
||||
import type { EncryptIDClaims } from "./auth";
|
||||
import { buildModuleCapabilities, MODULE_ROUTES } from "../lib/mi-module-routes";
|
||||
|
|
@ -58,6 +59,14 @@ mi.post("/ask", async (c) => {
|
|||
callerRole = "member";
|
||||
}
|
||||
|
||||
// ── Resolve space's enabled modules ──
|
||||
let enabledModuleIds: string[] | null = null;
|
||||
if (space) {
|
||||
await loadCommunity(space);
|
||||
const spaceDoc = getDocumentData(space);
|
||||
enabledModuleIds = spaceDoc?.meta?.enabledModules ?? null;
|
||||
}
|
||||
|
||||
// ── Resolve model ──
|
||||
const modelId = requestedModel || miRegistry.getDefaultModel();
|
||||
let providerInfo = miRegistry.resolveModel(modelId);
|
||||
|
|
@ -75,7 +84,11 @@ mi.post("/ask", async (c) => {
|
|||
}
|
||||
|
||||
// ── Build system prompt ──
|
||||
const moduleList = getModuleInfoList()
|
||||
const allModuleInfo = getModuleInfoList();
|
||||
const filteredModuleInfo = enabledModuleIds
|
||||
? allModuleInfo.filter(m => m.id === "rspace" || enabledModuleIds!.includes(m.id))
|
||||
: allModuleInfo;
|
||||
const moduleList = filteredModuleInfo
|
||||
.map((m) => `- **${m.name}** (${m.id}): ${m.icon} ${m.description}`)
|
||||
.join("\n");
|
||||
|
||||
|
|
@ -123,8 +136,10 @@ mi.post("/ask", async (c) => {
|
|||
}
|
||||
|
||||
// Module capabilities for enabled modules
|
||||
const enabledModuleIds = Object.keys(MODULE_ROUTES);
|
||||
const moduleCapabilities = buildModuleCapabilities(enabledModuleIds);
|
||||
const capabilityModuleIds = enabledModuleIds
|
||||
? Object.keys(MODULE_ROUTES).filter(id => enabledModuleIds!.includes(id))
|
||||
: Object.keys(MODULE_ROUTES);
|
||||
const moduleCapabilities = buildModuleCapabilities(capabilityModuleIds);
|
||||
|
||||
// Role-permission mapping
|
||||
const rolePermissions: Record<SpaceRoleString, string> = {
|
||||
|
|
@ -285,7 +300,7 @@ Use requireConfirm:true for destructive batches.`;
|
|||
});
|
||||
} catch (e: any) {
|
||||
console.error("mi: Provider error:", e.message);
|
||||
const fallback = generateFallbackResponse(query, currentModule, space, getModuleInfoList());
|
||||
const fallback = generateFallbackResponse(query, currentModule, space, filteredModuleInfo);
|
||||
return c.json({ response: fallback });
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2534,36 +2534,32 @@
|
|||
});
|
||||
|
||||
// Load module list for app switcher and tab bar + menu
|
||||
// Parallel fetch: modules + space-specific filter — setModules called once
|
||||
let moduleList = [];
|
||||
fetch("/api/modules").then(r => r.json()).then(data => {
|
||||
const spaceSlug = window.location.pathname.split("/").filter(Boolean)[0] || "demo";
|
||||
Promise.all([
|
||||
fetch("/api/modules").then(r => r.json()),
|
||||
fetch(`/api/spaces/${encodeURIComponent(spaceSlug)}/modules`).then(r => r.ok ? r.json() : null),
|
||||
]).then(([data, spaceData]) => {
|
||||
moduleList = data.modules || [];
|
||||
window.__rspaceAllModules = moduleList;
|
||||
document.querySelector("rstack-app-switcher")?.setModules(moduleList);
|
||||
const tb = document.querySelector("rstack-tab-bar");
|
||||
if (tb) tb.setModules(moduleList);
|
||||
|
||||
// Fetch space-specific enabled modules and apply filtering
|
||||
const spaceSlug = window.location.pathname.split("/").filter(Boolean)[0] || "demo";
|
||||
fetch(`/api/spaces/${encodeURIComponent(spaceSlug)}/modules`)
|
||||
.then(r => r.ok ? r.json() : null)
|
||||
.then(spaceData => {
|
||||
if (!spaceData) return;
|
||||
const enabledIds = spaceData.enabledModules; // null = all
|
||||
const enabledIds = spaceData?.enabledModules ?? null;
|
||||
window.__rspaceEnabledModules = enabledIds;
|
||||
if (enabledIds) {
|
||||
const enabledSet = new Set(enabledIds);
|
||||
const filtered = moduleList.filter(m => m.id === "rspace" || enabledSet.has(m.id));
|
||||
document.querySelector("rstack-app-switcher")?.setModules(filtered);
|
||||
const tb2 = document.querySelector("rstack-tab-bar");
|
||||
if (tb2) tb2.setModules(filtered);
|
||||
}
|
||||
|
||||
const visible = enabledIds
|
||||
? moduleList.filter(m => m.id === "rspace" || new Set(enabledIds).has(m.id))
|
||||
: moduleList;
|
||||
|
||||
document.querySelector("rstack-app-switcher")?.setModules(visible);
|
||||
const tb = document.querySelector("rstack-tab-bar");
|
||||
if (tb) tb.setModules(visible);
|
||||
|
||||
// Initialize folk-rapp filtering
|
||||
customElements.whenDefined("folk-rapp").then(() => {
|
||||
const FolkRApp = customElements.get("folk-rapp");
|
||||
if (FolkRApp?.setEnabledModules) FolkRApp.setEnabledModules(enabledIds);
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
}).catch(() => {});
|
||||
|
||||
// React to runtime module toggling from app switcher
|
||||
|
|
|
|||
Loading…
Reference in New Issue