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
+27 -1
View File
@@ -8,6 +8,7 @@ import type { Provider, SessionMeta, Settings } from "@/types";
import { extractErrorMessage } from "@/utils/errorUtils";
import { generateUUID } from "@/utils/uuid";
import { openclawKeys } from "@/hooks/useOpenClaw";
import { hermesKeys } from "@/hooks/useHermes";
export const useAddProviderMutation = (appId: AppId) => {
const queryClient = useQueryClient();
@@ -22,7 +23,7 @@ export const useAddProviderMutation = (appId: AppId) => {
) => {
let id: string;
if (appId === "opencode" || appId === "openclaw") {
if (appId === "opencode" || appId === "openclaw" || appId === "hermes") {
if (
providerInput.category === "omo" ||
providerInput.category === "omo-slim"
@@ -75,6 +76,12 @@ export const useAddProviderMutation = (appId: AppId) => {
});
}
if (appId === "hermes") {
await queryClient.invalidateQueries({
queryKey: hermesKeys.health,
});
}
try {
await providersApi.updateTrayMenu();
} catch (trayError) {
@@ -127,6 +134,11 @@ export const useUpdateProviderMutation = (appId: AppId) => {
queryKey: openclawKeys.health,
});
}
if (appId === "hermes") {
await queryClient.invalidateQueries({
queryKey: hermesKeys.health,
});
}
toast.success(
t("notifications.updateSuccess", {
defaultValue: "供应商更新成功",
@@ -180,6 +192,12 @@ export const useDeleteProviderMutation = (appId: AppId) => {
});
}
if (appId === "hermes") {
await queryClient.invalidateQueries({
queryKey: hermesKeys.health,
});
}
try {
await providersApi.updateTrayMenu();
} catch (trayError) {
@@ -244,6 +262,14 @@ export const useSwitchProviderMutation = (appId: AppId) => {
queryKey: openclawKeys.health,
});
}
if (appId === "hermes") {
await queryClient.invalidateQueries({
queryKey: hermesKeys.liveProviderIds,
});
await queryClient.invalidateQueries({
queryKey: hermesKeys.health,
});
}
try {
await providersApi.updateTrayMenu();