feat(webui): add skills marketplace
This commit is contained in:
@@ -26,7 +26,12 @@ import type {
|
||||
SettingsUpdate,
|
||||
SidebarStatePayload,
|
||||
SkillDetail,
|
||||
SkillActionPayload,
|
||||
SkillInstallPayload,
|
||||
SkillsPayload,
|
||||
SkillsSearchPayload,
|
||||
SkillsTrendsPayload,
|
||||
SkillsTrendingPayload,
|
||||
SlashCommand,
|
||||
SlashCommandLifecycle,
|
||||
TranscriptionSettingsUpdate,
|
||||
@@ -310,6 +315,87 @@ export async function fetchSkillDetail(
|
||||
);
|
||||
}
|
||||
|
||||
export async function updateSkillEnabled(
|
||||
token: string,
|
||||
name: string,
|
||||
enabled: boolean,
|
||||
base: string = "",
|
||||
): Promise<SkillActionPayload> {
|
||||
const params = new URLSearchParams({ name, enabled: String(enabled) });
|
||||
return request<SkillActionPayload>(
|
||||
`${base}/api/webui/skills/update?${params}`,
|
||||
token,
|
||||
);
|
||||
}
|
||||
|
||||
export async function deleteSkill(
|
||||
token: string,
|
||||
name: string,
|
||||
base: string = "",
|
||||
): Promise<SkillActionPayload> {
|
||||
const params = new URLSearchParams({ name });
|
||||
return request<SkillActionPayload>(
|
||||
`${base}/api/webui/skills/delete?${params}`,
|
||||
token,
|
||||
);
|
||||
}
|
||||
|
||||
export async function searchMarketplaceSkills(
|
||||
token: string,
|
||||
query: string,
|
||||
base: string = "",
|
||||
): Promise<SkillsSearchPayload> {
|
||||
const params = new URLSearchParams({ q: query });
|
||||
return request<SkillsSearchPayload>(
|
||||
`${base}/api/webui/skills/search?${params}`,
|
||||
token,
|
||||
undefined,
|
||||
API_READ_TIMEOUT_MS,
|
||||
);
|
||||
}
|
||||
|
||||
export async function fetchTrendingMarketplaceSkills(
|
||||
token: string,
|
||||
base: string = "",
|
||||
): Promise<SkillsTrendingPayload> {
|
||||
return request<SkillsTrendingPayload>(
|
||||
`${base}/api/webui/skills/trending`,
|
||||
token,
|
||||
undefined,
|
||||
API_READ_TIMEOUT_MS,
|
||||
);
|
||||
}
|
||||
|
||||
export async function fetchMarketplaceSkillTrends(
|
||||
token: string,
|
||||
skillIds: string[],
|
||||
base: string = "",
|
||||
): Promise<SkillsTrendsPayload> {
|
||||
const params = new URLSearchParams();
|
||||
skillIds.forEach((id) => params.append("id", id));
|
||||
return request<SkillsTrendsPayload>(
|
||||
`${base}/api/webui/skills/trends?${params}`,
|
||||
token,
|
||||
undefined,
|
||||
API_READ_TIMEOUT_MS,
|
||||
);
|
||||
}
|
||||
|
||||
export async function installMarketplaceSkill(
|
||||
token: string,
|
||||
source: string,
|
||||
skill: string,
|
||||
base: string = "",
|
||||
): Promise<SkillInstallPayload> {
|
||||
const params = new URLSearchParams({ source, skill });
|
||||
return request<SkillInstallPayload>(
|
||||
`${base}/api/webui/skills/install?${params}`,
|
||||
token,
|
||||
undefined,
|
||||
150_000,
|
||||
);
|
||||
}
|
||||
|
||||
export async function deleteSession(
|
||||
token: string,
|
||||
key: string,
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { SkillsPayload } from "@/lib/types";
|
||||
|
||||
export const SKILLS_CHANGED_EVENT = "nanobot:skills-changed";
|
||||
|
||||
export function isSkillsPayload(value: unknown): value is SkillsPayload {
|
||||
return (
|
||||
!!value
|
||||
&& typeof value === "object"
|
||||
&& Array.isArray((value as { skills?: unknown }).skills)
|
||||
);
|
||||
}
|
||||
|
||||
export function notifySkillsChanged(payload: SkillsPayload): void {
|
||||
if (typeof window === "undefined") return;
|
||||
window.dispatchEvent(new CustomEvent<SkillsPayload>(SKILLS_CHANGED_EVENT, {
|
||||
detail: payload,
|
||||
}));
|
||||
}
|
||||
@@ -178,6 +178,8 @@ export interface SkillSummary {
|
||||
name: string;
|
||||
description: string;
|
||||
source: "workspace" | "builtin" | string;
|
||||
enabled?: boolean;
|
||||
deletable?: boolean;
|
||||
available: boolean;
|
||||
unavailable_reason?: string;
|
||||
}
|
||||
@@ -189,13 +191,64 @@ export interface SkillRequirements {
|
||||
missing_env: string[];
|
||||
}
|
||||
|
||||
export interface SkillInstallOption {
|
||||
id: string;
|
||||
kind: string;
|
||||
label: string;
|
||||
command: string;
|
||||
}
|
||||
|
||||
export interface SkillDetail extends SkillSummary {
|
||||
requirements: SkillRequirements;
|
||||
install_options?: SkillInstallOption[];
|
||||
raw_markdown: string;
|
||||
}
|
||||
|
||||
export interface SkillsPayload { skills: SkillSummary[]; }
|
||||
|
||||
export interface SkillActionPayload extends SkillsPayload {
|
||||
last_action: {
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
deleted: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface MarketplaceSkillSummary {
|
||||
id: string;
|
||||
skill_id: string;
|
||||
name: string;
|
||||
source: string;
|
||||
installs: number;
|
||||
url: string;
|
||||
installed: boolean;
|
||||
rank?: number;
|
||||
}
|
||||
|
||||
export interface SkillsSearchPayload {
|
||||
query: string;
|
||||
skills: MarketplaceSkillSummary[];
|
||||
install_supported: boolean;
|
||||
}
|
||||
|
||||
export interface SkillsTrendingPayload {
|
||||
skills: MarketplaceSkillSummary[];
|
||||
period: "24h";
|
||||
install_supported: boolean;
|
||||
}
|
||||
|
||||
export interface SkillsTrendsPayload {
|
||||
trends: Record<string, number[]>;
|
||||
}
|
||||
|
||||
export interface SkillInstallPayload extends SkillsPayload {
|
||||
last_action: {
|
||||
installed: boolean;
|
||||
already_installed: boolean;
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
|
||||
/** Structured UI blob on ``progress`` WS frames; channels may add more ``kind`` values later. */
|
||||
export interface AgentUIBlob {
|
||||
kind: string;
|
||||
|
||||
Reference in New Issue
Block a user