refactor(omo): deduplicate OMO/OMO Slim via OmoVariant parameterization

Introduce OmoVariant struct with STANDARD/SLIM constants to eliminate
~250 lines of copy-pasted code across DAO, service, commands, and
frontend layers. Adding a new OMO variant now requires only a single
const declaration instead of duplicating ~400 lines.
This commit is contained in:
Jason
2026-02-19 21:11:58 +08:00
parent 8e219b5eb1
commit 1b71dc721c
10 changed files with 493 additions and 741 deletions
+134 -178
View File
@@ -3,192 +3,148 @@ import { omoApi, omoSlimApi } from "@/lib/api/omo";
import * as configApi from "@/lib/api/config";
import type { OmoGlobalConfig } from "@/types/omo";
export const omoKeys = {
all: ["omo"] as const,
globalConfig: () => [...omoKeys.all, "global-config"] as const,
currentProviderId: () => [...omoKeys.all, "current-provider-id"] as const,
providerCount: () => [...omoKeys.all, "provider-count"] as const,
};
// ── Factory ────────────────────────────────────────────────────
function invalidateOmoQueries(queryClient: ReturnType<typeof useQueryClient>) {
queryClient.invalidateQueries({ queryKey: omoKeys.globalConfig() });
queryClient.invalidateQueries({ queryKey: ["providers"] });
queryClient.invalidateQueries({ queryKey: omoKeys.currentProviderId() });
queryClient.invalidateQueries({ queryKey: omoKeys.providerCount() });
function createOmoQueryKeys(prefix: string) {
return {
all: [prefix] as const,
globalConfig: () => [prefix, "global-config"] as const,
currentProviderId: () => [prefix, "current-provider-id"] as const,
providerCount: () => [prefix, "provider-count"] as const,
};
}
export function useOmoGlobalConfig(enabled = true) {
return useQuery({
queryKey: omoKeys.globalConfig(),
enabled,
queryFn: async (): Promise<OmoGlobalConfig> => {
const raw = await configApi.getCommonConfigSnippet("omo");
if (!raw) {
return {
id: "global",
disabledAgents: [],
disabledMcps: [],
disabledHooks: [],
disabledSkills: [],
updatedAt: new Date().toISOString(),
};
}
try {
return JSON.parse(raw) as OmoGlobalConfig;
} catch (error) {
console.warn(
"[omo] invalid global config json, fallback to defaults",
error,
);
return {
id: "global",
disabledAgents: [],
disabledMcps: [],
disabledHooks: [],
disabledSkills: [],
updatedAt: new Date().toISOString(),
};
}
},
});
}
export function useCurrentOmoProviderId(enabled = true) {
return useQuery({
queryKey: omoKeys.currentProviderId(),
queryFn: omoApi.getCurrentOmoProviderId,
enabled,
});
}
export function useOmoProviderCount(enabled = true) {
return useQuery({
queryKey: omoKeys.providerCount(),
queryFn: omoApi.getOmoProviderCount,
enabled,
});
}
export function useSaveOmoGlobalConfig() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: OmoGlobalConfig) => {
const jsonStr = JSON.stringify(input);
await configApi.setCommonConfigSnippet("omo", jsonStr);
},
onSuccess: () => invalidateOmoQueries(queryClient),
});
}
export function useReadOmoLocalFile() {
return useMutation({
mutationFn: () => omoApi.readLocalFile(),
});
}
export function useDisableCurrentOmo() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: () => omoApi.disableCurrentOmo(),
onSuccess: () => invalidateOmoQueries(queryClient),
});
}
// ============================================================================
// OMO Slim query hooks
// ============================================================================
export const omoSlimKeys = {
all: ["omo-slim"] as const,
globalConfig: () => [...omoSlimKeys.all, "global-config"] as const,
currentProviderId: () => [...omoSlimKeys.all, "current-provider-id"] as const,
providerCount: () => [...omoSlimKeys.all, "provider-count"] as const,
};
function invalidateOmoSlimQueries(
queryClient: ReturnType<typeof useQueryClient>,
function createOmoQueryHooks(
variant: "omo" | "omo-slim",
api: typeof omoApi | typeof omoSlimApi,
) {
queryClient.invalidateQueries({ queryKey: omoSlimKeys.globalConfig() });
queryClient.invalidateQueries({ queryKey: ["providers"] });
queryClient.invalidateQueries({
queryKey: omoSlimKeys.currentProviderId(),
});
queryClient.invalidateQueries({ queryKey: omoSlimKeys.providerCount() });
const keys = createOmoQueryKeys(variant);
const snippetKey = variant === "omo" ? "omo" : "omo_slim";
function invalidateAll(queryClient: ReturnType<typeof useQueryClient>) {
queryClient.invalidateQueries({ queryKey: keys.globalConfig() });
queryClient.invalidateQueries({ queryKey: ["providers"] });
queryClient.invalidateQueries({ queryKey: keys.currentProviderId() });
queryClient.invalidateQueries({ queryKey: keys.providerCount() });
}
function useGlobalConfig(enabled = true) {
return useQuery({
queryKey: keys.globalConfig(),
enabled,
queryFn: async (): Promise<OmoGlobalConfig> => {
const raw = await configApi.getCommonConfigSnippet(snippetKey);
if (!raw) {
return {
id: "global",
disabledAgents: [],
disabledMcps: [],
disabledHooks: [],
disabledSkills: [],
updatedAt: new Date().toISOString(),
};
}
try {
return JSON.parse(raw) as OmoGlobalConfig;
} catch (error) {
console.warn(
`[${variant}] invalid global config json, fallback to defaults`,
error,
);
return {
id: "global",
disabledAgents: [],
disabledMcps: [],
disabledHooks: [],
disabledSkills: [],
updatedAt: new Date().toISOString(),
};
}
},
});
}
function useCurrentProviderId(enabled = true) {
return useQuery({
queryKey: keys.currentProviderId(),
queryFn:
"getCurrentOmoProviderId" in api
? (api as typeof omoApi).getCurrentOmoProviderId
: (api as typeof omoSlimApi).getCurrentProviderId,
enabled,
});
}
function useProviderCount(enabled = true) {
return useQuery({
queryKey: keys.providerCount(),
queryFn:
"getOmoProviderCount" in api
? (api as typeof omoApi).getOmoProviderCount
: (api as typeof omoSlimApi).getProviderCount,
enabled,
});
}
function useSaveGlobalConfig() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: OmoGlobalConfig) => {
const jsonStr = JSON.stringify(input);
await configApi.setCommonConfigSnippet(snippetKey, jsonStr);
},
onSuccess: () => invalidateAll(queryClient),
});
}
function useReadLocalFile() {
return useMutation({
mutationFn: () => api.readLocalFile(),
});
}
function useDisableCurrent() {
const queryClient = useQueryClient();
return useMutation({
mutationFn:
"disableCurrentOmo" in api
? (api as typeof omoApi).disableCurrentOmo
: (api as typeof omoSlimApi).disableCurrent,
onSuccess: () => invalidateAll(queryClient),
});
}
return {
keys,
useGlobalConfig,
useCurrentProviderId,
useProviderCount,
useSaveGlobalConfig,
useReadLocalFile,
useDisableCurrent,
};
}
export function useOmoSlimGlobalConfig(enabled = true) {
return useQuery({
queryKey: omoSlimKeys.globalConfig(),
enabled,
queryFn: async (): Promise<OmoGlobalConfig> => {
const raw = await configApi.getCommonConfigSnippet("omo_slim");
if (!raw) {
return {
id: "global",
disabledAgents: [],
disabledMcps: [],
disabledHooks: [],
disabledSkills: [],
updatedAt: new Date().toISOString(),
};
}
try {
return JSON.parse(raw) as OmoGlobalConfig;
} catch (error) {
console.warn(
"[omo-slim] invalid global config json, fallback to defaults",
error,
);
return {
id: "global",
disabledAgents: [],
disabledMcps: [],
disabledHooks: [],
disabledSkills: [],
updatedAt: new Date().toISOString(),
};
}
},
});
}
// ── Instances ──────────────────────────────────────────────────
export function useCurrentOmoSlimProviderId(enabled = true) {
return useQuery({
queryKey: omoSlimKeys.currentProviderId(),
queryFn: omoSlimApi.getCurrentProviderId,
enabled,
});
}
const omoHooks = createOmoQueryHooks("omo", omoApi);
const omoSlimHooks = createOmoQueryHooks("omo-slim", omoSlimApi);
export function useOmoSlimProviderCount(enabled = true) {
return useQuery({
queryKey: omoSlimKeys.providerCount(),
queryFn: omoSlimApi.getProviderCount,
enabled,
});
}
// ── Backward-compatible exports ────────────────────────────────
export function useSaveOmoSlimGlobalConfig() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: OmoGlobalConfig) => {
const jsonStr = JSON.stringify(input);
await configApi.setCommonConfigSnippet("omo_slim", jsonStr);
},
onSuccess: () => invalidateOmoSlimQueries(queryClient),
});
}
export const omoKeys = omoHooks.keys;
export const omoSlimKeys = omoSlimHooks.keys;
export function useReadOmoSlimLocalFile() {
return useMutation({
mutationFn: () => omoSlimApi.readLocalFile(),
});
}
export const useOmoGlobalConfig = omoHooks.useGlobalConfig;
export const useCurrentOmoProviderId = omoHooks.useCurrentProviderId;
export const useOmoProviderCount = omoHooks.useProviderCount;
export const useSaveOmoGlobalConfig = omoHooks.useSaveGlobalConfig;
export const useReadOmoLocalFile = omoHooks.useReadLocalFile;
export const useDisableCurrentOmo = omoHooks.useDisableCurrent;
export function useDisableCurrentOmoSlim() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: () => omoSlimApi.disableCurrent(),
onSuccess: () => invalidateOmoSlimQueries(queryClient),
});
}
export const useOmoSlimGlobalConfig = omoSlimHooks.useGlobalConfig;
export const useCurrentOmoSlimProviderId = omoSlimHooks.useCurrentProviderId;
export const useOmoSlimProviderCount = omoSlimHooks.useProviderCount;
export const useSaveOmoSlimGlobalConfig = omoSlimHooks.useSaveGlobalConfig;
export const useReadOmoSlimLocalFile = omoSlimHooks.useReadLocalFile;
export const useDisableCurrentOmoSlim = omoSlimHooks.useDisableCurrent;