feat(FN-3260): document static slot-host rendering contract

Documents the static slot-host rendering contract in `docs/PLUGIN_AUTHORING.md`, clarifying how plugins should interact with the rendering system.

Fusion-Task-Id: FN-3260
This commit is contained in:
Fusion
2026-05-04 20:13:09 -07:00
committed by gsxdsm
parent e0e871555d
commit fccec582f4
15 changed files with 283 additions and 234 deletions

View File

@@ -27,7 +27,6 @@ const PluginManager = lazy(() => import("./PluginManager").then((m) => ({ defaul
const PiExtensionsManager = lazy(() => import("./PiExtensionsManager").then((m) => ({ default: m.PiExtensionsManager })));
import { ClaudeCliProviderCard } from "./ClaudeCliProviderCard";
import { CliBinaryPanel } from "./CliBinaryPanel";
import { DroidCliProviderCard } from "./DroidCliProviderCard";
import { LlamaCppProviderCard } from "./LlamaCppProviderCard";
import { HermesRuntimeCard } from "./HermesRuntimeCard";
import { OpenClawRuntimeCard } from "./OpenClawRuntimeCard";
@@ -44,7 +43,6 @@ import { useConfirm } from "../hooks/useConfirm";
import { useMobileKeyboard } from "../hooks/useMobileKeyboard";
import { useMobileScrollLock } from "../hooks/useMobileScrollLock";
import { useNodes } from "../hooks/useNodes";
import { usePluginUiSlots } from "../hooks/usePluginUiSlots";
import { useViewportMode } from "../hooks/useViewportMode";
import { NodeHealthDot } from "./NodeHealthDot";
import { filterVisibleOnboardingAndSettingsProviders } from "./providerVisibility";
@@ -439,7 +437,6 @@ export function SettingsModal({
} = useWorkspaceFileBrowser("project", overlapPathPickerIndex !== null, projectId);
const { nodes } = useNodes();
const { getSlotsForId } = usePluginUiSlots(projectId);
const experimentalFeatures = form.experimentalFeatures ?? {};
const remoteAccessEnabled = isExperimentalFeatureEnabled(experimentalFeatures, "remoteAccess");
const researchViewEnabled = isExperimentalFeatureEnabled(experimentalFeatures, "researchView");
@@ -5047,11 +5044,7 @@ export function SettingsModal({
// CLI-backed providers live in whichever bucket matches their current
// auth state (Authenticated when signed in, Available otherwise).
const claudeCliProvider = cliAuthProviders.find((p) => p.id === "claude-cli");
const droidCliProvider = cliAuthProviders.find((p) => p.id === "droid-cli");
const llamaCppProvider = cliAuthProviders.find((p) => p.id === "llama-cpp");
const hasDroidPluginSlot = getSlotsForId("settings-provider-card").some(
(entry) => entry.pluginId === "fusion-plugin-droid-runtime",
);
const claudeCliCard = claudeCliProvider ? (
<ClaudeCliProviderCard
compact
@@ -5061,15 +5054,6 @@ export function SettingsModal({
}}
/>
) : null;
const droidCliCard = droidCliProvider && !hasDroidPluginSlot ? (
<DroidCliProviderCard
compact
authenticated={droidCliProvider.authenticated}
onToggled={() => {
void loadAuthStatus();
}}
/>
) : null;
const llamaCppCard = llamaCppProvider ? (
<LlamaCppProviderCard
compact
@@ -5082,12 +5066,10 @@ export function SettingsModal({
const showAuthenticatedGroup =
authenticatedProviders.length > 0
|| (claudeCliProvider?.authenticated ?? false)
|| ((droidCliProvider?.authenticated ?? false) && !hasDroidPluginSlot)
|| (llamaCppProvider?.authenticated ?? false);
const showAvailableGroup =
unauthenticatedProviders.length > 0
|| (claudeCliProvider && !claudeCliProvider.authenticated)
|| (droidCliProvider && !droidCliProvider.authenticated && !hasDroidPluginSlot)
|| (llamaCppProvider && !llamaCppProvider.authenticated);
return (
<>
@@ -5100,8 +5082,18 @@ export function SettingsModal({
</div>
) : (
<div className="auth-panel-body">
<PluginSlot slotId="settings-provider-card" projectId={projectId} renderPlaceholder={false} />
<PluginSlot slotId="settings-integration-card" projectId={projectId} renderPlaceholder={false} />
<PluginSlot
slotId="settings-provider-card"
projectId={projectId}
renderPlaceholder={false}
actions={{ refreshAuthProviders: () => { void loadAuthStatus(); } }}
/>
<PluginSlot
slotId="settings-integration-card"
projectId={projectId}
renderPlaceholder={false}
actions={{ refreshAuthProviders: () => { void loadAuthStatus(); } }}
/>
{!showAuthenticatedGroup && (
<div className="auth-section-hint">
Sign in to at least one provider to get started with AI models.
@@ -5111,7 +5103,6 @@ export function SettingsModal({
<div className="auth-provider-group">
<div className="auth-group-label">Authenticated</div>
{claudeCliProvider?.authenticated && claudeCliCard}
{droidCliProvider?.authenticated && droidCliCard}
{llamaCppProvider?.authenticated && llamaCppCard}
{authenticatedProviders.map((provider) => (
<div key={provider.id} className="auth-provider-card auth-provider-card--authenticated">
@@ -5206,7 +5197,6 @@ export function SettingsModal({
<div className="auth-provider-group">
<div className="auth-group-label">Available</div>
{claudeCliProvider && !claudeCliProvider.authenticated && claudeCliCard}
{droidCliProvider && !droidCliProvider.authenticated && droidCliCard}
{llamaCppProvider && !llamaCppProvider.authenticated && llamaCppCard}
{unauthenticatedProviders.map((provider) => (
<div key={provider.id} className="auth-provider-card">