fix(cli): enable group selection, quota billing and custom error codes for CLI accounts
Some checks failed
CI / test (push) Has been cancelled
CI / frontend (push) Has been cancelled
CI / golangci-lint (push) Has been cancelled
Security Scan / backend-security (push) Has been cancelled
Security Scan / frontend-security (push) Has been cancelled

- GroupsView: add 'kimi' to platformOptions/platformFilterOptions so users
can create kimi platform groups
- CreateAccountModal: show quota controls for cli type; inject quota limits
on submit; add custom_error_codes in CLI creation flow
- EditAccountModal: show quota controls for cli type; save quota limits on
submit
- Remove redundant duplicate quota control block that caused TS build error

[布偶猫/Opus🐾]
This commit is contained in:
openclaw
2026-04-24 02:02:29 +08:00
parent e746e82c39
commit 55ca0ad687
3 changed files with 20 additions and 64 deletions

View File

@@ -1575,9 +1575,9 @@
</div>
</div>
<!-- 配额控制 (Anthropic apikey/bedrock: 配额限制 + 亲和) -->
<!-- 配额控制 (apikey/bedrock/cli: 配额限制 + 亲和) -->
<div
v-if="form.platform === 'anthropic' && (form.type === 'apikey' || form.type === 'bedrock')"
v-if="form.type === 'apikey' || form.type === 'bedrock' || form.type === 'cli'"
class="border-t border-gray-200 pt-4 dark:border-dark-600 space-y-4"
>
<div class="mb-3">
@@ -1627,58 +1627,6 @@
/>
</div>
<!-- 配额控制 ( Anthropic apikey/bedrock) -->
<div
v-else-if="form.type === 'apikey' || form.type === 'bedrock'"
class="border-t border-gray-200 pt-4 dark:border-dark-600 space-y-4"
>
<div class="mb-3">
<h3 class="input-label mb-0 text-base font-semibold">{{ t('admin.accounts.quotaControl.title') }}</h3>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
{{ t('admin.accounts.quotaLimitHint') }}
</p>
</div>
<QuotaLimitCard
:totalLimit="editQuotaLimit"
:dailyLimit="editQuotaDailyLimit"
:weeklyLimit="editQuotaWeeklyLimit"
:quotaNotifyGlobalEnabled="quotaNotifyGlobalEnabled"
:quotaNotifyDailyEnabled="quotaNotifyState.daily.enabled"
:quotaNotifyDailyThreshold="quotaNotifyState.daily.threshold"
:quotaNotifyDailyThresholdType="quotaNotifyState.daily.thresholdType"
:quotaNotifyWeeklyEnabled="quotaNotifyState.weekly.enabled"
:quotaNotifyWeeklyThreshold="quotaNotifyState.weekly.threshold"
:quotaNotifyWeeklyThresholdType="quotaNotifyState.weekly.thresholdType"
:quotaNotifyTotalEnabled="quotaNotifyState.total.enabled"
:quotaNotifyTotalThreshold="quotaNotifyState.total.threshold"
:quotaNotifyTotalThresholdType="quotaNotifyState.total.thresholdType"
:dailyResetMode="editDailyResetMode"
:dailyResetHour="editDailyResetHour"
:weeklyResetMode="editWeeklyResetMode"
:weeklyResetDay="editWeeklyResetDay"
:weeklyResetHour="editWeeklyResetHour"
:resetTimezone="editResetTimezone"
@update:totalLimit="editQuotaLimit = $event"
@update:dailyLimit="editQuotaDailyLimit = $event"
@update:weeklyLimit="editQuotaWeeklyLimit = $event"
@update:quotaNotifyDailyEnabled="quotaNotifyState.daily.enabled = $event"
@update:quotaNotifyDailyThreshold="quotaNotifyState.daily.threshold = $event"
@update:quotaNotifyDailyThresholdType="quotaNotifyState.daily.thresholdType = $event"
@update:quotaNotifyWeeklyEnabled="quotaNotifyState.weekly.enabled = $event"
@update:quotaNotifyWeeklyThreshold="quotaNotifyState.weekly.threshold = $event"
@update:quotaNotifyWeeklyThresholdType="quotaNotifyState.weekly.thresholdType = $event"
@update:quotaNotifyTotalEnabled="quotaNotifyState.total.enabled = $event"
@update:quotaNotifyTotalThreshold="quotaNotifyState.total.threshold = $event"
@update:quotaNotifyTotalThresholdType="quotaNotifyState.total.thresholdType = $event"
@update:dailyResetMode="editDailyResetMode = $event"
@update:dailyResetHour="editDailyResetHour = $event"
@update:weeklyResetMode="editWeeklyResetMode = $event"
@update:weeklyResetDay="editWeeklyResetDay = $event"
@update:weeklyResetHour="editWeeklyResetHour = $event"
@update:resetTimezone="editResetTimezone = $event"
/>
</div>
<!-- OpenAI OAuth Model Mapping (OAuth 类型没有 apikey 容器需要独立的模型映射区域) -->
<div
v-if="form.platform === 'openai' && accountCategory === 'oauth-based'"
@@ -4235,6 +4183,12 @@ const handleSubmit = async () => {
credentials.pool_mode_retry_count = normalizePoolModeRetryCount(poolModeRetryCount.value)
}
// Add custom error codes if enabled
if (customErrorCodesEnabled.value) {
credentials.custom_error_codes_enabled = true
credentials.custom_error_codes = [...selectedErrorCodes.value]
}
applyInterceptWarmup(credentials, interceptWarmupRequests.value, 'create')
if (!applyTempUnschedConfig(credentials)) {
return
@@ -4574,9 +4528,9 @@ const createAccountAndFinish = async (
if (!applyTempUnschedConfig(credentials)) {
return
}
// Inject quota limits for apikey/bedrock accounts
// Inject quota limits for apikey/bedrock/cli accounts
let finalExtra = extra
if (type === 'apikey' || type === 'bedrock') {
if (type === 'apikey' || type === 'bedrock' || type === 'cli') {
const quotaExtra: Record<string, unknown> = { ...(extra || {}) }
if (editQuotaLimit.value != null && editQuotaLimit.value > 0) {
quotaExtra.quota_limit = editQuotaLimit.value

View File

@@ -1311,9 +1311,9 @@
</div>
</div>
<!-- 配额控制 (Anthropic apikey/bedrock: 配额限制 + 亲和) -->
<!-- 配额控制 (Anthropic apikey/bedrock/cli: 配额限制 + 亲和) -->
<div
v-if="account?.platform === 'anthropic' && (account?.type === 'apikey' || account?.type === 'bedrock')"
v-if="account?.platform === 'anthropic' && (account?.type === 'apikey' || account?.type === 'bedrock' || account?.type === 'cli')"
class="border-t border-gray-200 pt-4 dark:border-dark-600 space-y-4"
>
<div class="mb-3">
@@ -1362,9 +1362,9 @@
@update:quotaNotifyTotalThresholdType="quotaNotifyState.total.thresholdType = $event"
/>
</div>
<!-- 配额控制 ( Anthropic apikey/bedrock) -->
<!-- 配额控制 ( Anthropic apikey/bedrock/cli) -->
<div
v-else-if="account?.type === 'apikey' || account?.type === 'bedrock'"
v-else-if="account?.type === 'apikey' || account?.type === 'bedrock' || account?.type === 'cli'"
class="border-t border-gray-200 pt-4 dark:border-dark-600 space-y-4"
>
<div class="mb-3">
@@ -2351,8 +2351,8 @@ const syncFormFromAccount = (newAccount: Account | null) => {
}
}
// Load quota limit for apikey/bedrock accounts (bedrock quota is also loaded in its own branch above)
if (newAccount.type === 'apikey' || newAccount.type === 'bedrock') {
// Load quota limit for apikey/bedrock/cli accounts
if (newAccount.type === 'apikey' || newAccount.type === 'bedrock' || newAccount.type === 'cli') {
const quotaVal = extra?.quota_limit as number | undefined
editQuotaLimit.value = (quotaVal && quotaVal > 0) ? quotaVal : null
const dailyVal = extra?.quota_daily_limit as number | undefined
@@ -3440,8 +3440,8 @@ const handleSubmit = async () => {
updatePayload.extra = newExtra
}
// For apikey/bedrock accounts, handle quota_limit in extra
if (props.account.type === 'apikey' || props.account.type === 'bedrock') {
// For apikey/bedrock/cli accounts, handle quota_limit in extra
if (props.account.type === 'apikey' || props.account.type === 'bedrock' || props.account.type === 'cli') {
const currentExtra = (updatePayload.extra as Record<string, unknown>) ||
(props.account.extra as Record<string, unknown>) || {}
const newExtra: Record<string, unknown> = { ...currentExtra }

View File

@@ -2783,6 +2783,7 @@ const platformOptions = computed(() => [
{ value: "openai", label: "OpenAI" },
{ value: "gemini", label: "Gemini" },
{ value: "antigravity", label: "Antigravity" },
{ value: "kimi", label: "Kimi" },
]);
const platformFilterOptions = computed(() => [
@@ -2791,6 +2792,7 @@ const platformFilterOptions = computed(() => [
{ value: "openai", label: "OpenAI" },
{ value: "gemini", label: "Gemini" },
{ value: "antigravity", label: "Antigravity" },
{ value: "kimi", label: "Kimi" },
]);
const editStatusOptions = computed(() => [