/**
 * Shared destination derivation for generated ("fresh" / zero-to-one) projects.
 *
 * Both kickoff paths — `start_variants(mode='zero_to_one')` and the
 * source-grounded `create_zero_to_one_project` — turn a prompt into the same
 * thing: a slugified subproject directory under `<workspaceRoot>/.rivet/<slug>/`.
 * They used to derive it with two near-identical copies of the same logic,
 * which had already drifted: the `start_variants` path skipped
 * `normalizeWorkspaceRoot`, so a `destinationParent` that already sat inside a
 * `.rivet/` tree produced a nested `.rivet/<slug>/.rivet/<slug2>` that breaks
 * preview/history path resolution. Centralizing here removes the duplication
 * and gives both paths the nesting guard.
 */
import type { ErrorCode } from './errors';
/**
 * Slugify a prompt into a directory-safe kebab-case name with a short random
 * suffix so concurrent calls with the same prompt don't collide.
 */
export declare const slugifyPrompt: (prompt: string) => string;
/**
 * Collapse a candidate workspace root back to the real workspace when it points
 * inside a `.rivet/` tree.
 *
 * The editor bridge can become bound to a previously generated subproject
 * (`<root>/.rivet/<slug>`) — e.g. after the user opens that subproject in the
 * visual editor. Without this guard the next zero-to-one session would resolve
 * its `destinationParent` to that subproject and join `.rivet/<slug>` onto it,
 * producing a nested `<root>/.rivet/<slug>/.rivet/<slug2>`. That nesting breaks
 * preview/history path resolution (everything is rooted at `workspaceRoot`), so
 * generated variants land on disk but render blank on click.
 *
 * Truncating at the segment before the first `.rivet` keeps the single-`.rivet`
 * invariant. Idempotent: a path with no `.rivet` segment is returned unchanged.
 */
export declare const normalizeWorkspaceRoot: (candidate: string) => string;
export interface GeneratedDestination {
    slug: string;
    /** The user's working dir that owns all Rivet artifacts for the session. */
    workspaceRoot: string;
    /** Where the generated subproject's files live:
     *  `<workspaceRoot>/.rivet/<slug>/`. */
    destinationPath: string;
}
export interface DeriveDestinationFailure {
    errorCode: ErrorCode;
    message: string;
}
export type DeriveGeneratedDestinationResult = ({
    ok: true;
} & GeneratedDestination) | ({
    ok: false;
} & DeriveDestinationFailure);
/**
 * Resolve the destination for a generated project from a prompt.
 *
 * Destination-parent default chain: explicit `destinationParent` arg →
 * currently-open editor project → MCP server cwd. cwd (not homedir) so
 * generated projects land near where the user is actually working rather than
 * dumped at the home root.
 *
 * Returns a discriminated result so each caller can format the failure in its
 * own response shape. On `ok`, the parent of `destinationPath` has been
 * created so the materialize step at commit time has a directory to write into.
 */
export declare function deriveGeneratedDestination(args: {
    prompt: string;
    destinationParent?: string;
    editorProjectPath?: string;
    cwd: () => string;
    /** Override for the emptiness probe (tests). Defaults to isDestinationEmpty. */
    destinationIsEmpty?: (destinationPath: string) => boolean;
    /** Override for directory creation (tests). Defaults to fs.mkdirSync. */
    mkdir?: (dir: string) => void;
}): DeriveGeneratedDestinationResult;
//# sourceMappingURL=generatedDestination.d.ts.map