import { type ExecFileSyncOptions } from 'node:child_process'; /** Mustache-style token substituted in projected markdown at install/sync time. See design.md §5. */ export declare const KYRO_CLI_PLACEHOLDER = "{{KYRO_CLI}}"; export interface KyroInvocation { /** Full shell-invocable string, e.g. "kyro" or "node ~/.agents/kyro/current/dist/cli.js". */ raw: string; command: string; args: string[]; } /** * Pure: no I/O (besides the defaulted platform probe). Given whether a *durable* `kyro` is on * PATH and the runtime root to fall back to, produces the invocation value. `kyroRoot` is the * single active runtime path, so persisted invocations survive package updates without pinning * historical version directories. * * Callers must not pass `true` for ephemeral package-manager bins (npx cache, etc.) — those * vanish after the install process exits and leave agents with a dead `kyro` string. * * Windows note: npm on win32 installs `.cmd`/`.ps1` shims, not a real `kyro.exe`. Node's spawn * without `shell: true` ignores PATHEXT, so `spawnSync("kyro")` always fails with ENOENT, and * spawning `kyro.cmd` directly is blocked since CVE-2024-27980 (EINVAL on Node >= 18.20 / 20.12 * / 22). A bare `"kyro"` manifest value can therefore never be self-spawned by doctor on * Windows, even on a healthy global install. Persist the `node /dist/cli.js` form on * win32 instead — it works in shells and via execFileSync alike. */ export declare function buildInvocation(durableKyroOnPath: boolean, kyroRoot: string, platform?: NodeJS.Platform): KyroInvocation; /** * True when a resolved binary path is only available for the life of a package-manager * one-shot (npx / dlx cache), not as a permanent install. Pure: no I/O. * * `npx kyro-ai install` puts `…/.npm/_npx/…/node_modules/.bin/kyro` on PATH for the child * process only. Treating that as durable caused install to persist `kyroInvocation: "kyro"`, * which then failed for agents after npx exited. */ export declare function isEphemeralPackageManagerPath(resolvedPath: string): boolean; /** * Resolve `kyro` on PATH to an absolute path, or null if missing / unresolvable. * Infra probe — isolated so pure helpers stay unit-testable. */ export declare function resolveKyroBinaryPath(): string | null; /** First shell-visible command, before following a symlink (needed to verify npm ownership). */ export declare function resolveKyroCommandPath(): string | null; export type GlobalKyroOwnership = 'npm-owned' | 'missing' | 'foreign' | 'ambiguous'; export interface GlobalKyroProbe { commandPath: string | null; npmPrefix: string | null; npmRoot: string | null; /** Real path of commandPath; null if the shim cannot be inspected. */ realPath: string | null; /** Windows npm .cmd text; null if unreadable. */ shimContents?: string | null; platform?: NodeJS.Platform; } /** * Classify the effective PATH command against the npm installation that update would change. * A durable command alone is insufficient: pnpm and a second npm prefix are different installs. * This function performs no I/O, so previews can use it without modifying any state. */ export declare function classifyGlobalKyroOwnership(probe: GlobalKyroProbe): GlobalKyroOwnership; /** * True only when `kyro` resolves on PATH to a non-ephemeral binary that will still exist * after the current process exits (global npm install, user shim, etc.). * Swallows all errors and defaults to `false` (safe fallback: the node form always works * once dist/ is projected). */ export declare function isDurableKyroOnPath(): boolean; /** * @deprecated Prefer {@link isDurableKyroOnPath}. Kept as an alias so existing call sites * and comments that say `isKyroOnPath` keep the durable semantics. */ export declare function isKyroOnPath(): boolean; export declare function resolveKyroInvocation(): KyroInvocation; /** * Authoritative CLI invocation for this machine. * * Source of truth is the global runtime manifest (`~/.agents/kyro/current/manifest.json`). * Falls back to a live PATH probe when the manifest is missing or has no invocation yet. * Never reads project `.agents/kyro/kyro.json` — that field is legacy and stripped on install/sync * so one workspace refresh cannot leave N other projects with a stale bare `"kyro"`. */ export declare function getPersistedKyroInvocation(): string; /** Expand a leading `~` to the user's home dir; execFileSync does no shell expansion. */ export declare function expandInvocationHome(segment: string): string; /** Split an invocation string into tokens, respecting single/double quotes (for paths with spaces). Pure. */ export declare function splitInvocation(raw: string): string[]; /** True for legacy bare invocations (`kyro`, `kyro.cmd`, `kyro-ai`, …) with no script path. Pure. */ export declare function isBareKyroInvocation(raw: string): boolean; /** Absolute path to the projected runtime entrypoint (`/dist/cli.js`). */ export declare function resolveProjectedCliJs(kyroRoot?: string): string; export interface InvocationSpawn { command: string; args: string[]; /** True when a legacy bare `kyro` was mapped to `node /dist/cli.js` (win32). */ fallbackUsed: boolean; } /** * Map a persisted invocation string to a directly-spawnable argv (no shell). * * - `node ` → `process.execPath ` (same runtime, no PATH lookup). * - bare `kyro` on win32 → `process.execPath ` (PATHEXT is ignored * by spawn without shell, and direct `.cmd` spawn is blocked since CVE-2024-27980, so the * bare form can never self-spawn on Windows even on a healthy install). * - everything else → split + `~`-expanded as-is (POSIX semantics unchanged). * * Pure except for the defaulted platform probe; pass `platform` explicitly in unit tests to * simulate Windows on POSIX CI. */ export declare function resolveInvocationSpawn(raw: string, platform?: NodeJS.Platform): InvocationSpawn; /** * execFileSync wrapper for persisted invocations. Uses {@link resolveInvocationSpawn} so legacy * bare-`kyro` manifests self-spawn on Windows via the projected runtime instead of ENOENT, and * retries once via the projected runtime when a direct win32 spawn fails with ENOENT/EINVAL * (covers quoted/absolute shim spellings the static check may miss). */ export declare function execKyroInvocationSync(raw: string, extraArgs: string[], options: ExecFileSyncOptions & { encoding: 'utf8'; }): string; export declare function execKyroInvocationSync(raw: string, extraArgs: string[], options?: ExecFileSyncOptions): Buffer; //# sourceMappingURL=invocation.d.ts.map