MCPcopy Index your code
hub / github.com/scriptscat/scriptcat / parseSkillZip

Function parseSkillZip

src/pkg/utils/skill.ts:82–152  ·  view source on GitHub ↗
(data: ArrayBuffer)

Source from the content-addressed store, hash-verified

80
81// 解析 Skill ZIP 包:提取 SKILL.md、scripts/*.js、references/*
82export async function parseSkillZip(data: ArrayBuffer): Promise<{
83 skillMd: string;
84 scripts: Array<{ name: string; code: string }>;
85 references: Array<{ name: string; content: string }>;
86}> {
87 const zip = await loadAsyncJSZip(data);
88 const files: Record<string, JSZipObject> = {};
89 zip.forEach((relativePath, file) => {
90 files[relativePath] = file;
91 });
92
93 // 查找 SKILL.cat.md 或 SKILL.md:根目录或第一层子目录
94 let skillMdPath = "";
95 let prefix = "";
96 const skillFileNames = ["SKILL.cat.md", "SKILL.md"];
97 for (const path of Object.keys(files)) {
98 const normalized = path.replace(/\\/g, "/");
99 const fileName = normalized.split("/").pop() || "";
100 if (!skillFileNames.includes(fileName)) continue;
101 const parts = normalized.split("/");
102 if (parts.length === 1) {
103 // 根目录(优先 SKILL.cat.md)
104 if (!skillMdPath || fileName === "SKILL.cat.md") {
105 skillMdPath = path;
106 prefix = "";
107 }
108 } else if (parts.length === 2 && !skillMdPath) {
109 // 一层子目录
110 skillMdPath = path;
111 prefix = parts[0] + "/";
112 }
113 }
114
115 if (!skillMdPath) {
116 throw new Error("ZIP 包中未找到 SKILL.cat.md 或 SKILL.md");
117 }
118
119 const skillMd: string = await files[skillMdPath].async("string");
120
121 // 提取 scripts/*.js
122 const scripts: Array<{ name: string; code: string }> = [];
123 const scriptsDir = prefix + "scripts/";
124 for (const [path, file] of Object.entries(files)) {
125 if (file.dir) continue;
126 const normalized = path.replace(/\\/g, "/");
127 if (normalized.startsWith(scriptsDir) && normalized.endsWith(".js")) {
128 const name = normalized.slice(scriptsDir.length);
129 if (name && !name.includes("/")) {
130 const code = await file.async("string");
131 scripts.push({ name, code });
132 }
133 }
134 }
135
136 // 提取 references/*
137 const references: Array<{ name: string; content: string }> = [];
138 const refsDir = prefix + "references/";
139 for (const [path, file] of Object.entries(files)) {

Callers 2

skill.test.tsFile · 0.90
getSkillInstallDataMethod · 0.90

Calls 8

loadAsyncJSZipFunction · 0.90
forEachMethod · 0.80
keysMethod · 0.80
popMethod · 0.80
asyncMethod · 0.80
entriesMethod · 0.80
pushMethod · 0.80
sliceMethod · 0.45

Tested by

no test coverage detected