feat(ui): use acp method to load skills (#9959)

This commit is contained in:
Lifei Zhou
2026-06-24 05:46:33 +10:00
committed by GitHub
parent 06076f0875
commit 527fcfc288
2 changed files with 49 additions and 11 deletions
+43
View File
@@ -0,0 +1,43 @@
import type { SourceEntry, SourceType } from '@aaif/goose-sdk';
import { getAcpClient } from './acpConnection';
const SKILL_SOURCE_TYPES: SourceType[] = ['skill', 'builtinSkill'];
const inFlightSkillSourceLoads = new Map<string, Promise<SourceEntry[]>>();
export async function listSkillSources(projectDir: string): Promise<SourceEntry[]> {
const inFlightLoad = inFlightSkillSourceLoads.get(projectDir);
if (inFlightLoad) {
return inFlightLoad;
}
const load = loadSkillSources(projectDir);
inFlightSkillSourceLoads.set(projectDir, load);
try {
return await load;
} finally {
if (inFlightSkillSourceLoads.get(projectDir) === load) {
inFlightSkillSourceLoads.delete(projectDir);
}
}
}
async function loadSkillSources(projectDir: string): Promise<SourceEntry[]> {
const client = await getAcpClient();
const responses = await Promise.all(
SKILL_SOURCE_TYPES.map((type) =>
client.goose.sourcesList_unstable({
type,
projectDir,
})
)
);
return responses
.flatMap((response) => response.sources)
.sort(
(a, b) =>
a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }) ||
a.path.localeCompare(b.path)
);
}
@@ -5,12 +5,12 @@ import { Card } from '../ui/card';
import { Button } from '../ui/button';
import { Skeleton } from '../ui/skeleton';
import { MainPanelLayout } from '../Layout/MainPanelLayout';
import { getSlashCommands } from '../../api';
import { errorMessage } from '../../utils/conversionUtils';
import { getInitialWorkingDir } from '../../utils/workingDir';
import { defineMessages, useIntl } from '../../i18n';
import { SearchView } from '../conversation/SearchView';
import { getSearchShortcutText } from '../../utils/keyboardShortcuts';
import { listSkillSources } from '../../acp/sources';
const i18n = defineMessages({
errorLoadingSkills: {
@@ -118,16 +118,11 @@ export default function SkillsView() {
setShowSkeleton(true);
setShowContent(false);
setError(null);
const response = await getSlashCommands({
query: { working_dir: getInitialWorkingDir() },
throwOnError: true,
});
const skillEntries: SkillEntry[] = (response.data?.commands ?? [])
.filter((cmd) => cmd.command_type === 'Skill')
.map((cmd) => ({
name: cmd.command,
description: cmd.help,
}));
const sources = await listSkillSources(getInitialWorkingDir());
const skillEntries: SkillEntry[] = sources.map((source) => ({
name: source.name,
description: source.description,
}));
setSkills(skillEntries);
} catch (err) {
setError(errorMessage(err, 'Failed to load skills'));