feat(FN-2984): add droid CLI path reconciliation extension

The merge introduces a new droid CLI extension with path reconciliation across daemon, dashboard, and serve commands, along with supporting core and engine utilities. It also removes stale lint suppression comments (FN-2983). Tests cover the new CLI extension and path reconciliation logic.

Fusion-Task-Id: FN-2984
This commit is contained in:
Fusion
2026-05-01 12:23:55 -07:00
committed by gsxdsm
parent 4789c2ab07
commit 337f84aa5f
4 changed files with 123 additions and 3 deletions

View File

@@ -34,7 +34,7 @@ import {
type AgentSession,
type ToolDefinition,
} from "@mariozechner/pi-coding-agent";
import { getEnabledPiExtensionPaths, getFusionAgentDir, getLegacyPiAgentDir, reconcileClaudeCliPaths, resolvePiExtensionProjectRoot } from "@fusion/core";
import { getEnabledPiExtensionPaths, getFusionAgentDir, getLegacyPiAgentDir, reconcileClaudeCliPaths, reconcileDroidCliPaths, resolvePiExtensionProjectRoot } from "@fusion/core";
import {
resolveSessionSkills,
createSkillsOverrideFromSelection,
@@ -731,6 +731,29 @@ function resolveVendoredClaudeCliEntry(): string | null {
}
}
/**
* Resolve the absolute path to Fusion's vendored `@fusion/droid-cli`
* extension entry. Used by `registerExtensionProviders` to ensure the
* vendored extension always wins over any externally-installed `droid-cli`.
*/
function resolveVendoredDroidCliEntry(): string | null {
try {
const require_ = createRequire(import.meta.url);
const pkgJsonPath = require_.resolve("@fusion/droid-cli/package.json");
const pkgJson = JSON.parse(readFileSync(pkgJsonPath, "utf-8")) as {
pi?: { extensions?: unknown };
};
const extensions = pkgJson.pi?.extensions;
if (!Array.isArray(extensions) || extensions.length === 0) return null;
const entry = extensions[0];
if (typeof entry !== "string" || entry.length === 0) return null;
const path = resolve(dirname(pkgJsonPath), entry);
return existsSync(path) ? path : null;
} catch {
return null;
}
}
async function registerExtensionProviders(cwd: string, modelRegistry: ModelRegistry): Promise<void> {
try {
const agentDir = getPackageManagerAgentDir();
@@ -755,8 +778,17 @@ async function registerExtensionProviders(cwd: string, modelRegistry: ModelRegis
vendoredClaudeCli,
);
const extensionsResult = await discoverAndLoadExtensions(
// Prefer Fusion's vendored `@fusion/droid-cli` over any external
// `droid-cli` install. Side-by-side loading of two extensions that
// register the same provider name produces unpredictable winners.
const vendoredDroidCli = resolveVendoredDroidCliEntry();
const doubleReconciledPaths = reconcileDroidCliPaths(
reconciledPaths,
vendoredDroidCli,
);
const extensionsResult = await discoverAndLoadExtensions(
doubleReconciledPaths,
cwd,
join(resolvePiExtensionProjectRoot(cwd), ".fusion", "disabled-auto-extension-discovery"),
);