import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; declare function changelogTagUrl(version: string): string; export type InstallMethod = "global" | "npx" | "local-dev" | "unknown"; export interface DetectInstallOptions { pkgRoot: string; globalRoot?: string | null; } export declare function detectInstallMethod(opts: DetectInstallOptions): InstallMethod; type ExecFileAsync = (cmd: string, args: readonly string[], options?: { timeout?: number; }) => Promise<{ stdout: string; stderr: string; }>; export declare function getNpmGlobalRoot(runner?: ExecFileAsync): Promise; export interface ChangelogResult { tag: string; version: string; body: string; } export declare function fetchChangelog(fetchImpl: typeof fetch): Promise; declare function parseTriple(v: string): [number, number, number] | null; export declare function isUpgrade(current: string, latest: string): boolean; export declare function composeChangelogSummary(current: string, latest: string, body: string): string; export interface UpgradeResult { ok: boolean; stdout: string; stderr: string; } export declare function runUpgrade(spec: string, runner?: ExecFileAsync): Promise; interface DriftCache { lastSeenBundledForgeVersion: string | null; promptedForVersions: string[]; } declare function defaultCacheDir(): string; declare function driftCachePath(dir: string): string; declare function readDriftCache(dir: string): Promise; declare function writeDriftCache(dir: string, cache: DriftCache): Promise; export interface DriftCheckOptions { currentBundledForgeVersion: string; notify(message: string, level: "info" | "warning" | "error"): void; cacheDir?: string; } export declare function checkBundledForgeDrift(opts: DriftCheckOptions): Promise; interface CliPreflightResult { method: InstallMethod; upgraded: boolean; cliOldVersion?: string; cliNewVersion?: string; npmVersion?: string; npmFetchFailed: boolean; bundledForgeVersion: string; } /** * Read the bundled update.md and apply forge-cli-specific patches. * * The plugin's update.md was written for Claude Code's plugin architecture. * forge-cli uses a bundled payload instead of the Claude Code plugin cache, * so we patch: * * 1. FORGE_ROOT: Replace CLAUDE_PLUGIN_ROOT with bundled payload path * 2. IS_CANARY: Always true (bundle is never in /.claude/plugins/) * 3. DISTRIBUTION: Always "forge@forge" (no marketplace detection) * 4. migrations.json: Bundle puts it in .schemas/, not top-level * 5. CLI preflight result: Instruct agent to skip Steps 1/2A/3 * 6. CLAUDE_PLUGIN_DATA: Replace with bundled payload path * * All patches are pure string replacements — no AST parsing needed. * If a patch target isn't found, we log a warning but don't crash * (the agent may still be able to follow the unpatched instructions * partially). */ export declare function composeUpdateKickoff(updateMd: string, bundleRoot: string, preflight: CliPreflightResult): string; export interface RegisterUpdateCommandOptions { pkgRoot: string; currentCliVersion: string; fetchImpl?: typeof fetch; globalRootResolver?: () => Promise; upgradeRunner?: (spec: string) => Promise; /** Override bundled-forge version for drift cache */ currentBundledForgeVersion?: string; /** Override drift cache path */ driftCacheDir?: string; } export declare function registerForgeUpdateCommand(pi: ExtensionAPI, opts: RegisterUpdateCommandOptions): void; export declare const __test__: { parseTriple: typeof parseTriple; driftCachePath: typeof driftCachePath; readDriftCache: typeof readDriftCache; writeDriftCache: typeof writeDriftCache; defaultCacheDir: typeof defaultCacheDir; PKG_NAME: string; NPM_DIST_TAGS_URL: string; changelogTagUrl: typeof changelogTagUrl; UPGRADE_TIMEOUT_MS: number; NPM_ROOT_TIMEOUT_MS: number; PROBE_TIMEOUT_MS: number; composeUpdateKickoff: typeof composeUpdateKickoff; }; export {};