feat: offer local plugin install in git checkouts

This commit is contained in:
Peter Steinberger
2026-01-15 09:07:14 +00:00
parent e0f69a2294
commit 5599603bdb
4 changed files with 51 additions and 10 deletions

View File

@@ -79,7 +79,10 @@ describe("ensureOnboardingPluginInstalled", () => {
select: vi.fn(async () => "local") as WizardPrompter["select"],
});
const cfg: ClawdbotConfig = {};
vi.mocked(fs.existsSync).mockReturnValue(true);
vi.mocked(fs.existsSync).mockImplementation((value) => {
const raw = String(value);
return raw.endsWith(`${path.sep}.git`) || raw.endsWith(`${path.sep}extensions${path.sep}zalo`);
});
const result = await ensureOnboardingPluginInstalled({
cfg,
@@ -104,7 +107,10 @@ describe("ensureOnboardingPluginInstalled", () => {
confirm,
});
const cfg: ClawdbotConfig = {};
vi.mocked(fs.existsSync).mockReturnValue(true);
vi.mocked(fs.existsSync).mockImplementation((value) => {
const raw = String(value);
return raw.endsWith(`${path.sep}.git`) || raw.endsWith(`${path.sep}extensions${path.sep}zalo`);
});
installPluginFromNpmSpec.mockResolvedValue({
ok: false,
error: "nope",

View File

@@ -16,7 +16,24 @@ type InstallResult = {
installed: boolean;
};
function resolveLocalPath(entry: ChannelPluginCatalogEntry, workspaceDir?: string): string | null {
function hasGitWorkspace(workspaceDir?: string): boolean {
const candidates = new Set<string>();
candidates.add(path.join(process.cwd(), ".git"));
if (workspaceDir && workspaceDir !== process.cwd()) {
candidates.add(path.join(workspaceDir, ".git"));
}
for (const candidate of candidates) {
if (fs.existsSync(candidate)) return true;
}
return false;
}
function resolveLocalPath(
entry: ChannelPluginCatalogEntry,
workspaceDir: string | undefined,
allowLocal: boolean,
): string | null {
if (!allowLocal) return null;
const raw = entry.install.localPath?.trim();
if (!raw) return null;
const candidates = new Set<string>();
@@ -113,7 +130,8 @@ export async function ensureOnboardingPluginInstalled(params: {
}): Promise<InstallResult> {
const { entry, prompter, runtime, workspaceDir } = params;
let next = params.cfg;
const localPath = resolveLocalPath(entry, workspaceDir);
const allowLocal = hasGitWorkspace(workspaceDir);
const localPath = resolveLocalPath(entry, workspaceDir, allowLocal);
const choice = await promptInstallChoice({
entry,
localPath,