feat(openclaw): add additive mode frontend support

- Add getOpenClawLiveProviderIds() API for querying live config
- Update ProviderList to query OpenClaw live IDs
- Rename isOpenCodeMode to isAdditiveMode (covers OpenCode + OpenClaw)
- Update ProviderCard shouldAutoQuery and isActiveProvider logic
- Update App.tsx onRemoveFromConfig and invalidateQueries for OpenClaw
This commit is contained in:
Jason
2026-02-05 15:25:33 +08:00
parent 47f2c47a2f
commit 715e9e89c4
5 changed files with 57 additions and 14 deletions

View File

@@ -425,10 +425,19 @@ function App() {
const { provider, action } = confirmAction;
if (action === "remove") {
// Remove from live config only (for additive mode apps like OpenCode/OpenClaw)
// Does NOT delete from database - provider remains in the list
await providersApi.removeFromLiveConfig(provider.id, activeApp);
await queryClient.invalidateQueries({
queryKey: ["opencodeLiveProviderIds"],
});
// Invalidate queries to refresh the isInConfig state
if (activeApp === "opencode") {
await queryClient.invalidateQueries({
queryKey: ["opencodeLiveProviderIds"],
});
} else if (activeApp === "openclaw") {
await queryClient.invalidateQueries({
queryKey: ["openclawLiveProviderIds"],
});
}
toast.success(
t("notifications.removeFromConfigSuccess", {
defaultValue: "已从配置移除",
@@ -642,7 +651,7 @@ function App() {
setConfirmAction({ provider, action: "delete" })
}
onRemoveFromConfig={
activeApp === "opencode"
activeApp === "opencode" || activeApp === "openclaw"
? (provider) =>
setConfirmAction({ provider, action: "remove" })
: undefined

View File

@@ -62,10 +62,13 @@ export function ProviderActions({
const { t } = useTranslation();
const iconButtonClass = "h-8 w-8 p-1";
const isOpenCodeMode = appId === "opencode" && !isOmo;
// 累加模式应用OpenCode 非 OMO 和 OpenClaw
const isAdditiveMode =
(appId === "opencode" && !isOmo) || appId === "openclaw";
// 故障转移模式下的按钮逻辑(累加模式和 OMO 应用不支持故障转移)
const isFailoverMode =
!isOpenCodeMode && !isOmo && isAutoFailoverEnabled && onToggleFailover;
!isAdditiveMode && !isOmo && isAutoFailoverEnabled && onToggleFailover;
const handleMainButtonClick = () => {
if (isOmo) {
@@ -74,7 +77,8 @@ export function ProviderActions({
} else {
onSwitch();
}
} else if (isOpenCodeMode) {
} else if (isAdditiveMode) {
// 累加模式:切换配置状态(添加/移除)
if (isInConfig) {
if (onRemoveFromConfig) {
onRemoveFromConfig();
@@ -112,7 +116,8 @@ export function ProviderActions({
};
}
if (isOpenCodeMode) {
// 累加模式OpenCode 非 OMO / OpenClaw
if (isAdditiveMode) {
if (isInConfig) {
return {
disabled: false,
@@ -180,7 +185,7 @@ export function ProviderActions({
const canDelete = isOmo
? !(isLastOmo && isCurrent)
: isOpenCodeMode
: isAdditiveMode
? true
: !isCurrent;

View File

@@ -133,7 +133,10 @@ export function ProviderCard({
const usageEnabled = provider.meta?.usage_script?.enabled ?? false;
const shouldAutoQuery = appId === "opencode" ? isInConfig : isCurrent;
// 获取用量数据以判断是否有多套餐
// 累加模式应用OpenCode/OpenClaw使用 isInConfig 代替 isCurrent
const shouldAutoQuery =
appId === "opencode" || appId === "openclaw" ? isInConfig : isCurrent;
const autoQueryInterval = shouldAutoQuery
? provider.meta?.usage_script?.autoQueryInterval || 0
: 0;
@@ -176,9 +179,14 @@ export function ProviderCard({
onOpenWebsite(displayUrl);
};
// 判断是否是"当前使用中"的供应商
// - OMO 供应商:使用 isCurrent
// - 累加模式应用OpenCode 非 OMO / OpenClaw不存在"当前"概念,始终返回 false
// - 故障转移模式代理实际使用的供应商activeProviderId
// - 普通模式isCurrent
const isActiveProvider = isOmo
? isCurrent
: appId === "opencode"
: appId === "opencode" || appId === "openclaw"
? false
: isAutoFailoverEnabled
? activeProviderId === provider.id

View File

@@ -84,12 +84,25 @@ export function ProviderList({
enabled: appId === "opencode",
});
// OpenClaw: 查询 live 配置中的供应商 ID 列表,用于判断 isInConfig
const { data: openclawLiveIds } = useQuery({
queryKey: ["openclawLiveProviderIds"],
queryFn: () => providersApi.getOpenClawLiveProviderIds(),
enabled: appId === "openclaw",
});
// 判断供应商是否已添加到配置累加模式应用OpenCode/OpenClaw
const isProviderInConfig = useCallback(
(providerId: string): boolean => {
if (appId !== "opencode") return true; // 非 OpenCode 应用始终返回 true
return opencodeLiveIds?.includes(providerId) ?? false;
if (appId === "opencode") {
return opencodeLiveIds?.includes(providerId) ?? false;
}
if (appId === "openclaw") {
return openclawLiveIds?.includes(providerId) ?? false;
}
return true; // 其他应用始终返回 true
},
[appId, opencodeLiveIds],
[appId, opencodeLiveIds, openclawLiveIds],
);
const { data: isAutoFailoverEnabled } = useAutoFailoverEnabled(appId);

View File

@@ -98,6 +98,14 @@ export const providersApi = {
async getOpenCodeLiveProviderIds(): Promise<string[]> {
return await invoke("get_opencode_live_provider_ids");
},
/**
* 获取 OpenClaw live 配置中的供应商 ID 列表
* 用于前端判断供应商是否已添加到 openclaw.json
*/
async getOpenClawLiveProviderIds(): Promise<string[]> {
return await invoke("get_openclaw_live_provider_ids");
},
};
// ============================================================================