export declare const UNDEFINED: unique symbol;
export type UNDEFINED = typeof UNDEFINED;
type IsOptional<S extends object, K extends keyof S> = Omit<S, K> extends S ? true : false;
/**
 * A target is a partial state that can be used to update
 *
 * A Target in Mahler is by default 'relative', meaning that only property
 * changes and additions should be considered when comparing current and
 * target states for planning. Property deletion need to be done explicitely
 * via the `UNDEFINED` symbol. This allows a cleaner interface for for
 * defining system targets and allows the system state to have additional properties
 * than the target.
 *
 * Example: let's say we are modelling the state of two variables `x` and `y`.
 *
 * Given the current state `{x: 0}`, the target state `{y: 1}` means that the
 * planner needs to only to find a task that can create the variable `y` and increase its
 * value to `1`. The final expected state should be `{x: 0, y:1}` (assuming nothing else changes `x`).
 *
 * If the goal was to remove the variable `x` at the same time that variable `y` is introduced, the
 * target would need to be `{x: UNDEFINED, y: 1}`.
 *
 * A 'relative' target is the opposite to a 'strict' (or absolute) target, where what is passed to
 * the planner/agent describes exactly the desired state of the system is.
 *
 * In the previous example, the strict target `{y:1}` is equivalent to the relative target `{x: UNDEFINED, y: 1}`,
 * meaning the strict target describes the expected state of the system.
 */
export type Target<S> = S extends any[] | ((...args: any) => any) ? S : S extends object ? {
    [P in keyof S]?: IsOptional<S, P> extends true ? // Only optional properties can be deleted
    Target<S[P]> | UNDEFINED : Target<S[P]>;
} : S;
/**
 * A strict target describes the desired system state in an 'absolute' way
 *
 * Absolute, in this context, means that after a plan has been successfully been
 * found, the system state should look exactly like the given target.
 */
export type StrictTarget<S> = S extends any[] | ((...args: any) => any) ? S : S extends object ? {
    [P in keyof S]: IsOptional<S, P> extends true ? // Only optional properties can be undefined
    StrictTarget<S[P]> | undefined : StrictTarget<S[P]>;
} : S;
/**
 * Create a new relative target from the given strict target and the
 * current state.
 *
 * This will look any missing properties on the target and replace them with
 * `UNDEFINED` symbols in order to mark them for deletion.
 *
 * Because sometimes it is useful to have properties on the current state
 * that are not needed on the target, this function receives a
 * list of 'globs' indicating which properties to ignore. Properties in the `ignoreGlobs`
 * list will be skipped when marking properties to be deleted.
 *
 * Example.
 * ```
 * // Current state
 * const s = {x: 1, y:0, lastUpdated: '20240408T12:00:00Z'};
 *
 * // Calculate target state
 * const target = Target.fromStrict(s, {y: 1}, ['lastUpdated']);
 * console.log(target); // {x: UNDEFINED, y: 1}
 * ```
 *
 * Note that glob support is very limited, and only supports `*` as special characters.
 */
declare function fromStrict<S>(state: S, target: StrictTarget<S>, ignoreGlobs?: string[]): Target<S>;
export declare const Target: {
    /**
     * Create a new relative target from the given strict target and the
     * current state.
     *
     * @deprecated to be replaced by fromStrict
     */
    from: typeof fromStrict;
    fromStrict: typeof fromStrict;
};
export {};
