refactor: isolate clawhub skill search

This commit is contained in:
Shakker
2026-08-04 13:47:53 +01:00
committed by Shakker
parent ed1ddb6d55
commit bc0c47e901
5 changed files with 65 additions and 57 deletions
+27
View File
@@ -0,0 +1,27 @@
import type { GatewayBrowserClient } from "../../api/gateway.ts";
export type ClawHubSearchResult = {
score: number;
slug: string;
displayName: string;
summary?: string;
icon?: string | null;
version?: string;
updatedAt?: number;
};
export async function searchClawHub(
client: GatewayBrowserClient,
query: string,
signal?: AbortSignal,
): Promise<ClawHubSearchResult[]> {
if (!query.trim()) {
return [];
}
const response = await client.request<{ results: ClawHubSearchResult[] }>(
"skills.search",
{ query, limit: 20 },
{ signal },
);
return response?.results ?? [];
}
+1 -1
View File
@@ -4,6 +4,7 @@ import { expectDefined } from "@openclaw/normalization-core";
import { describe, expect, it, vi } from "vitest";
import { waitForFast } from "../../test-helpers/wait-for.ts";
import { createRuntimeConfigCapability } from "../config/index.ts";
import { searchClawHub } from "./clawhub-search.ts";
import {
installFromClawHub,
installSkill,
@@ -13,7 +14,6 @@ import {
refreshSkills,
reconcileSkillsAgentId,
saveSkillApiKey,
searchClawHub,
setSkillsAgentId,
updateSkillEdit,
updateSkillEnabled,
+35 -53
View File
@@ -11,6 +11,7 @@ import type {
SkillStatusReport,
} from "../../api/types.ts";
import { redactToolDetail } from "../browser-redact.ts";
import type { ClawHubSearchResult } from "./clawhub-search.ts";
import {
normalizeSkillApiKeyReplacement,
runSkillConfigMutation,
@@ -18,16 +19,6 @@ import {
type SkillConfigMutationOwner,
} from "./config-mutations.ts";
export type ClawHubSearchResult = {
score: number;
slug: string;
displayName: string;
summary?: string;
icon?: string | null;
version?: string;
updatedAt?: number;
};
export type ClawHubSkillDetail = {
skill: {
slug: string;
@@ -575,18 +566,33 @@ export async function updateSkillEnabled(
enabled: boolean,
canDispatch: () => boolean = () => true,
) {
await runSkillMutation(state, skillKey, async (client) => {
const refreshError = await runSkillConfigMutation(
state.runtimeConfig,
client,
{
skillKey,
enabled,
},
canDispatch,
);
return skillConfigMutationSuccess(enabled ? "Skill enabled" : "Skill disabled", refreshError);
});
await runSkillConfigUpdate(
state,
skillKey,
{ enabled },
enabled ? "Skill enabled" : "Skill disabled",
canDispatch,
);
}
async function runSkillConfigUpdate(
state: SkillsState,
skillKey: string,
patch: { enabled: boolean } | { apiKey: string },
message: string,
canDispatch: () => boolean,
) {
await runSkillMutation(state, skillKey, async (client) =>
skillConfigMutationSuccess(
message,
await runSkillConfigMutation(
state.runtimeConfig,
client,
{ skillKey, ...patch },
canDispatch,
),
),
);
}
export async function saveSkillApiKey(
@@ -598,21 +604,13 @@ export async function saveSkillApiKey(
if (!apiKey) {
return;
}
await runSkillMutation(state, skillKey, async (client) => {
const refreshError = await runSkillConfigMutation(
state.runtimeConfig,
client,
{
skillKey,
apiKey,
},
canDispatch,
);
return skillConfigMutationSuccess(
`API key saved — stored in openclaw.json (skills.entries.${skillKey})`,
refreshError,
);
});
await runSkillConfigUpdate(
state,
skillKey,
{ apiKey },
`API key saved — stored in openclaw.json (skills.entries.${skillKey})`,
canDispatch,
);
}
export async function installSkill(
@@ -637,22 +635,6 @@ export async function installSkill(
});
}
export async function searchClawHub(
client: GatewayBrowserClient,
query: string,
signal?: AbortSignal,
): Promise<ClawHubSearchResult[]> {
if (!query.trim()) {
return [];
}
const response = await client.request<{ results: ClawHubSearchResult[] }>(
"skills.search",
{ query, limit: 20 },
{ signal },
);
return response?.results ?? [];
}
export async function loadClawHubDetail(state: SkillsState, slug: string) {
if (!state.client || !state.connected) {
return;
+1 -2
View File
@@ -14,6 +14,7 @@ import { renderHubTabs } from "../../components/hub-tabs.ts";
import { renderSettingsWorkspace } from "../../components/settings-workspace.ts";
import { t } from "../../i18n/index.ts";
import { canCallGatewayMethod } from "../../lib/gateway-methods.ts";
import { searchClawHub, type ClawHubSearchResult } from "../../lib/skills/clawhub-search.ts";
import {
closeClawHubDetail,
installFromClawHub,
@@ -24,11 +25,9 @@ import {
refreshSkills,
reconcileSkillsAgentId,
saveSkillApiKey,
searchClawHub,
setSkillsAgentId,
updateSkillEdit,
updateSkillEnabled,
type ClawHubSearchResult,
type ClawHubSkillDetail,
type ClawHubSkillSecurityVerdict,
type SkillOperation,
+1 -1
View File
@@ -34,10 +34,10 @@ import {
isSkillAvailable,
renderSkillStatusChips,
} from "../../lib/skills-shared.ts";
import type { ClawHubSearchResult } from "../../lib/skills/clawhub-search.ts";
import {
clawhubVerdictKey,
type ClawHubSkillSecurityVerdict,
type ClawHubSearchResult,
type ClawHubSkillDetail,
type SkillOperation,
type SkillMessageMap,