def resolve_cache_info(
    ctx,
    ctx_index,
    args,
    kwargs,
    key_fn,
    func,
    *,
    residency="transient",
    operator_scoped=False,
    user_scoped=False,
    prompt_scoped=False,
    jwt_scoped=False,
    collection_name=None,
    max_size=None,
):
    """
    Resolves the cache key, store, and memory cache for a given function call,
    including scope-based keys.

    Returns:
        A tuple: (cache_key, store, memory_cache, skip_cache)
    """
    cache_disabled = not fo.config.execution_cache_enabled
    if cache_disabled:
        return None, None, None, True

    base_cache_key_tuple = _get_cache_key_tuple(
        ctx_index, args, kwargs, key_fn
    )

    scoped_cache_key_list, skip_cache = _get_scoped_cache_key_list(
        ctx,
        operator_scoped=operator_scoped,
        user_scoped=user_scoped,
        prompt_scoped=prompt_scoped,
        jwt_scoped=jwt_scoped,
    )

    cache_key_list = list(base_cache_key_tuple) + scoped_cache_key_list
    cache_key = _build_cache_key(cache_key_list)

    memory_cache = None
    store = None

    if residency == "ephemeral":
        func_id = _get_function_id(func)
        memory_cache = get_ephemeral_cache(func_id, max_size=max_size)
    elif residency == "hybrid":
        func_id = _get_function_id(func)
        memory_cache = get_ephemeral_cache(func_id, max_size=max_size)
        store = _get_store_for_func(
            func,
            dataset_id=ctx.dataset._doc.id,
            collection_name=collection_name,
        )
    elif residency == "transient":
        store = _get_store_for_func(
            func,
            dataset_id=ctx.dataset._doc.id,
            collection_name=collection_name,
        )

    return cache_key, store, memory_cache, skip_cache

    Resolves the cache key, store, and memory cache for a given function call,
    including scope-based keys.

    Returns:
        A tuple: (cache_key, store, memory_cache, skip_cache)
    
fiftyone/operators/cache/utils.py