mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-06-22 01:01:56 +08:00
Users need one settings surface to discover and install skills without manually navigating provider-specific directories. Add provider-backed global skill installation for Claude, Codex, Gemini, and Cursor, while keeping OpenCode read-only because it reuses other providers' skill locations. Add a responsive Skills settings tab with scoped discovery, search, refresh controls, markdown and folder uploads, upload feedback, and overflow-safe layouts. Validate bundled skill files and paths before writing them, preserve scripts and assets, and cover provider discovery and installation behavior with tests.
69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import os from 'node:os';
|
|
import path from 'node:path';
|
|
|
|
import { SkillsProvider } from '@/modules/providers/shared/skills/skills.provider.js';
|
|
import type { ProviderSkillSource } from '@/shared/types.js';
|
|
import {
|
|
addUniqueProviderSkillSource,
|
|
findTopmostGitRoot,
|
|
} from '@/shared/utils.js';
|
|
|
|
export class CodexSkillsProvider extends SkillsProvider {
|
|
constructor() {
|
|
super('codex');
|
|
}
|
|
|
|
protected async getSkillSources(workspacePath: string): Promise<ProviderSkillSource[]> {
|
|
const sources: ProviderSkillSource[] = [];
|
|
const seenRootDirs = new Set<string>();
|
|
const repoRoot = await findTopmostGitRoot(workspacePath);
|
|
|
|
addUniqueProviderSkillSource(sources, seenRootDirs, {
|
|
scope: 'repo',
|
|
rootDir: path.join(workspacePath, '.agents', 'skills'),
|
|
commandPrefix: '$',
|
|
});
|
|
|
|
if (repoRoot) {
|
|
// Codex checks repository skills at the launch folder, one folder above it,
|
|
// and the topmost git root; these can collapse to the same directory.
|
|
addUniqueProviderSkillSource(sources, seenRootDirs, {
|
|
scope: 'repo',
|
|
rootDir: path.join(path.dirname(workspacePath), '.agents', 'skills'),
|
|
commandPrefix: '$',
|
|
});
|
|
addUniqueProviderSkillSource(sources, seenRootDirs, {
|
|
scope: 'repo',
|
|
rootDir: path.join(repoRoot, '.agents', 'skills'),
|
|
commandPrefix: '$',
|
|
});
|
|
}
|
|
|
|
addUniqueProviderSkillSource(sources, seenRootDirs, {
|
|
scope: 'user',
|
|
rootDir: path.join(os.homedir(), '.agents', 'skills'),
|
|
commandPrefix: '$',
|
|
});
|
|
addUniqueProviderSkillSource(sources, seenRootDirs, {
|
|
scope: 'admin',
|
|
rootDir: path.join('/etc', 'codex', 'skills'),
|
|
commandPrefix: '$',
|
|
});
|
|
addUniqueProviderSkillSource(sources, seenRootDirs, {
|
|
scope: 'system',
|
|
rootDir: path.join(os.homedir(), '.codex', 'skills', '.system'),
|
|
commandPrefix: '$',
|
|
});
|
|
|
|
return sources;
|
|
}
|
|
|
|
protected async getGlobalSkillSource(): Promise<ProviderSkillSource> {
|
|
return {
|
|
scope: 'user',
|
|
rootDir: path.join(os.homedir(), '.agents', 'skills'),
|
|
commandPrefix: '$',
|
|
};
|
|
}
|
|
}
|