feat(sproutclaw): modularize webui, extensions, and agent config layout
Some checks failed
CI / build-check-test (push) Has been cancelled

Restructure local extensions into per-feature directories, split WebUI
into backend modules with slash commands and systemd support, and track
prompts/skills under .pi/agent for portable Gitea deployment.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
root
2026-06-10 16:57:08 +08:00
parent 11c3a3a399
commit cf5edd6394
132 changed files with 9288 additions and 1971 deletions

View File

@@ -5,9 +5,14 @@ import { type ExecutionEnv, type FileInfo, type Result, type Skill, toError } fr
const MAX_NAME_LENGTH = 64;
const MAX_DESCRIPTION_LENGTH = 1024;
const IGNORE_FILE_NAMES = [".gitignore", ".ignore", ".fdignore"];
const IGNORED_ROOT_SKILL_MARKDOWN = new Set(["README.md"]);
type IgnoreMatcher = ReturnType<typeof ignore>;
function isIgnoredRootSkillMarkdown(fileName: string): boolean {
return IGNORED_ROOT_SKILL_MARKDOWN.has(fileName) || fileName.toLowerCase() === "readme.md";
}
export type SkillDiagnosticCode =
| "file_info_failed"
| "list_failed"
@@ -165,7 +170,8 @@ async function loadSkillsFromDirInternal(
continue;
}
if (kind !== "file" || !includeRootFiles || !entry.name.endsWith(".md")) continue;
if (kind !== "file" || !includeRootFiles || !entry.name.endsWith(".md") || isIgnoredRootSkillMarkdown(entry.name))
continue;
const result = await loadSkillFromFile(env, fullPath);
if (result.skill) skills.push(result.skill);
diagnostics.push(...result.diagnostics);
@@ -234,6 +240,10 @@ async function loadSkillFromFile(
env: ExecutionEnv,
filePath: string,
): Promise<{ skill: Skill | null; diagnostics: SkillDiagnostic[] }> {
if (isIgnoredRootSkillMarkdown(basenameEnvPath(filePath))) {
return { skill: null, diagnostics: [] };
}
const diagnostics: SkillDiagnostic[] = [];
const rawContent = await env.readTextFile(filePath);
if (!rawContent.ok) {