BudgetProfile.java
/*******************************************************************************
* Copyright (c) 2026 Carsten Hammer.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Carsten Hammer
*******************************************************************************/
package org.sandbox.mining.core.budget;
import java.util.Arrays;
import java.util.Locale;
import java.util.stream.Collectors;
/**
* Preset budget profiles for LLM-backed mining runs.
* <p>
* The values are deliberately conservative for free-tier operation. They are
* intended as defaults; callers may still override the resulting request and
* commit limits explicitly.
* </p>
*/
public enum BudgetProfile {
/**
* Cheapest profile: one commit per request and low daily defaults.
*/
FREE(1, 50, 100),
/**
* Default profile: keeps the current batching behaviour but still offers
* explicit accounting hooks.
*/
BALANCED(4, 200, 800),
/**
* Full context profile: unlimited by default unless explicit limits are set.
*/
THOROUGH(4, 0, 0);
private final int recommendedCommitsPerRequest;
private final int defaultMaxRequests;
private final int defaultMaxCommits;
BudgetProfile(int recommendedCommitsPerRequest, int defaultMaxRequests,
int defaultMaxCommits) {
this.recommendedCommitsPerRequest = recommendedCommitsPerRequest;
this.defaultMaxRequests = defaultMaxRequests;
this.defaultMaxCommits = defaultMaxCommits;
}
/**
* @return recommended commits per LLM request for this profile
*/
public int recommendedCommitsPerRequest() {
return recommendedCommitsPerRequest;
}
/**
* @return default maximum LLM requests; {@code 0} means unlimited
*/
public int defaultMaxRequests() {
return defaultMaxRequests;
}
/**
* @return default maximum commits sent to the LLM; {@code 0} means unlimited
*/
public int defaultMaxCommits() {
return defaultMaxCommits;
}
/**
* Parse a profile name from CLI/configuration text.
* <p>
* Matching is case-insensitive; hyphens are treated as underscores so that
* {@code "free"} and {@code "FREE"} are both valid.
* </p>
*
* @param value the profile name
* @return the parsed profile
* @throws IllegalArgumentException if the profile is unknown, with a message
* that lists the supported profile names
*/
public static BudgetProfile parse(String value) {
if (value == null || value.isBlank()) {
return BALANCED;
}
String normalized = value.trim().toUpperCase(Locale.ROOT).replace('-', '_');
try {
return BudgetProfile.valueOf(normalized);
} catch (IllegalArgumentException e) {
String supported = Arrays.stream(BudgetProfile.values())
.map(Enum::name)
.collect(Collectors.joining(", ")); //$NON-NLS-1$
throw new IllegalArgumentException(
"Unknown budget profile: '" + value + "'. Supported profiles: " + supported); //$NON-NLS-1$ //$NON-NLS-2$
}
}
/**
* Apply this profile's batching recommendation unless the user explicitly
* provided a different value.
*
* @param currentValue value currently configured
* @param explicitlyConfigured whether the user configured the value explicitly
* @return effective commits-per-request value
*/
public int effectiveCommitsPerRequest(int currentValue,
boolean explicitlyConfigured) {
if (explicitlyConfigured) {
return currentValue;
}
return Math.max(1, recommendedCommitsPerRequest);
}
}