feat: add Hermes frontend types, API layer, and hooks (Phase 7)

- Add "hermes" to AppId union type and all exhaustive Record<AppId>
- Add HermesModelConfig, HermesAgentConfig, HermesEnvConfig types
- Add hermes field to VisibleApps, McpApps, ProxyTakeoverStatus
- Create src/lib/api/hermes.ts with Tauri invoke wrappers
- Create src/hooks/useHermes.ts with 5 query + 3 mutation hooks
- Register hermes in APP_IDS, APP_ICON_MAP (violet color scheme)
- Split MCP_SKILLS_APP_IDS into MCP_APP_IDS (includes hermes) and
  SKILLS_APP_IDS (excludes hermes, since Hermes has no Skills support)
- Wire hermes additive-mode into App.tsx (remove/duplicate handlers),
  ProviderList.tsx (live provider ID query + In Config badge),
  mutations.ts (cache invalidation on switch/add/delete)
- Add Hermes checkbox to McpFormModal
- Add basic hermes i18n keys (en/zh/ja)
This commit is contained in:
Jason
2026-04-15 17:41:33 +08:00
parent 576ff53a75
commit a0b585992a
23 changed files with 467 additions and 33 deletions
+131
View File
@@ -0,0 +1,131 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { hermesApi } from "@/lib/api/hermes";
import { providersApi } from "@/lib/api/providers";
import type {
HermesEnvConfig,
HermesAgentConfig,
HermesModelConfig,
} from "@/types";
/**
* Centralized query keys for all Hermes-related queries.
* Import this from any file that needs to invalidate Hermes caches.
*/
export const hermesKeys = {
all: ["hermes"] as const,
liveProviderIds: ["hermes", "liveProviderIds"] as const,
modelConfig: ["hermes", "modelConfig"] as const,
agentConfig: ["hermes", "agentConfig"] as const,
env: ["hermes", "env"] as const,
health: ["hermes", "health"] as const,
};
// ============================================================
// Query hooks
// ============================================================
/**
* Query live provider IDs from Hermes config.
* Used by ProviderList to show "In Config" badge.
*/
export function useHermesLiveProviderIds(enabled: boolean) {
return useQuery({
queryKey: hermesKeys.liveProviderIds,
queryFn: () => providersApi.getHermesLiveProviderIds(),
enabled,
});
}
/**
* Query model configuration.
*/
export function useHermesModelConfig(enabled: boolean) {
return useQuery({
queryKey: hermesKeys.modelConfig,
queryFn: () => hermesApi.getModelConfig(),
enabled,
});
}
/**
* Query agent configuration.
*/
export function useHermesAgentConfig() {
return useQuery({
queryKey: hermesKeys.agentConfig,
queryFn: () => hermesApi.getAgentConfig(),
staleTime: 30_000,
});
}
/**
* Query env configuration.
*/
export function useHermesEnv() {
return useQuery({
queryKey: hermesKeys.env,
queryFn: () => hermesApi.getEnv(),
staleTime: 30_000,
});
}
/**
* Query config health warnings.
*/
export function useHermesHealth(enabled: boolean) {
return useQuery({
queryKey: hermesKeys.health,
queryFn: () => hermesApi.scanHealth(),
staleTime: 30_000,
enabled,
});
}
// ============================================================
// Mutation hooks
// ============================================================
/**
* Save model config. Invalidates modelConfig and health queries on success.
* Toast notifications are handled by the component.
*/
export function useSaveHermesModelConfig() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (config: HermesModelConfig) => hermesApi.setModelConfig(config),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: hermesKeys.modelConfig });
queryClient.invalidateQueries({ queryKey: hermesKeys.health });
},
});
}
/**
* Save agent config. Invalidates agentConfig and health queries on success.
* Toast notifications are handled by the component.
*/
export function useSaveHermesAgentConfig() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (config: HermesAgentConfig) => hermesApi.setAgentConfig(config),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: hermesKeys.agentConfig });
queryClient.invalidateQueries({ queryKey: hermesKeys.health });
},
});
}
/**
* Save env config. Invalidates env and health queries on success.
* Toast notifications are handled by the component.
*/
export function useSaveHermesEnv() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (env: HermesEnvConfig) => hermesApi.setEnv(env),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: hermesKeys.env });
queryClient.invalidateQueries({ queryKey: hermesKeys.health });
},
});
}