feat(*): 模型协议 - 升级声明式协议、扩充官方插件并完善生成任务恢复

This commit is contained in:
ddCat
2026-09-01 16:47:03 +08:00
parent 3f4a9ea3d0
commit 4724f0767b
132 changed files with 4576 additions and 1420 deletions

View File

@@ -0,0 +1,70 @@
import { readFile, readdir, writeFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
const root = dirname(fileURLToPath(import.meta.url));
const contractStart = "<!-- YINGCE_MANIFEST_CONTRACT_START -->";
const contractEnd = "<!-- YINGCE_MANIFEST_CONTRACT_END -->";
const recursiveDocumentationPlaceholder =
"<当前插件的完整 documentation,由 README.md 与 docs/interface.md 拼接而成;为避免 JSON 递归,此处不重复展开正文。>";
function withoutGeneratedContract(document) {
const start = document.indexOf(contractStart);
if (start < 0) return document.trimEnd();
const end = document.indexOf(contractEnd, start);
if (end < 0) {
throw new Error("docs/interface.md contains an unterminated generated manifest contract");
}
return `${document.slice(0, start)}${document.slice(end + contractEnd.length)}`.trimEnd();
}
function renderContract(manifest) {
const contract = JSON.parse(JSON.stringify(manifest));
contract.documentation = recursiveDocumentationPlaceholder;
return `${contractStart}
## Manifest 完整接口定义
以下 JSON 与插件包内实际 \`manifest.json\` 逐字段一致,覆盖插件身份、权限、配置、鉴权、参数、校验、创建、Agent、查询、取消、结果下载、响应和 Agent 响应映射。\`documentation\` 字段的值就是当前完整文档;为避免文档在自身内部无限递归,JSON 中仅用等义占位文本表示正文。
\`\`\`json
${JSON.stringify(contract, null, 2)}
\`\`\`
${contractEnd}`;
}
const entries = await readdir(root, { withFileTypes: true });
const requestedPackageIDs = new Set(process.argv.slice(2).map((value) => value.trim()).filter(Boolean));
const packageDirectories = entries
.filter((entry) => entry.isDirectory())
.map((entry) => entry.name)
.filter((name) => requestedPackageIDs.size === 0 || requestedPackageIDs.has(name))
.sort();
let updated = 0;
for (const packageID of packageDirectories) {
const packageRoot = join(root, packageID);
let manifestSource;
try {
manifestSource = await readFile(join(packageRoot, "manifest.json"), "utf8");
} catch (error) {
if (error?.code === "ENOENT") continue;
throw error;
}
const manifest = JSON.parse(manifestSource);
const readme = (await readFile(join(packageRoot, "README.md"), "utf8")).trim();
const interfacePath = join(packageRoot, "docs", "interface.md");
const interfaceSource = await readFile(interfacePath, "utf8");
const interfaceDocument = `${withoutGeneratedContract(interfaceSource)}\n\n${renderContract(manifest)}\n`;
manifest.documentation = `${readme}\n\n---\n\n${interfaceDocument.trim()}\n`;
await writeFile(interfacePath, interfaceDocument);
await writeFile(join(packageRoot, "manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`);
updated += 1;
}
if (updated === 0) {
throw new Error("no protocol plugin manifests were found");
}
console.log(`embedded complete documentation into ${updated} protocol packages`);