feat: book-import 新增領域時同步產生對應的領域技能
- book.sh add-chapter 新增 --key、--skills-dir:建立章節頁並產生 skills/<key>/SKILL.md, 同步更新插件 README 領域表與 wiki 技能的指令清單 - book-import 新增領域的流程:確認標題、說明與 key,決定技能寫入位置,並提醒重新載入與提交 - 移除文件中寫死的「八章」 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
65bc192fae
commit
f36c522a24
@@ -5,7 +5,7 @@
|
||||
// chapters 列出章節(章號、標題、說明、篇數)
|
||||
// find <關鍵字>... 找已存在的主題(標題與內文)
|
||||
// add <章號> --title T --source S --file F 新增頁面(自動編號)
|
||||
// add-chapter <標題> <說明> 新增一章
|
||||
// add-chapter <標題> <說明> --key <名稱> [--skills-dir <目錄>] 新增一章並產生領域技能
|
||||
// index 重建章節頁、Home 目錄與每頁的上下頁導覽
|
||||
// lint [檔案...] 檢查頁面格式(不給檔案則檢查有變更的頁面)
|
||||
// diff 顯示尚未推送的變更
|
||||
@@ -193,13 +193,83 @@ function cmdAdd(args: string[]): void {
|
||||
console.log(`已新增:${name.slice(0, -3)}`);
|
||||
}
|
||||
|
||||
function cmdAddChapter(title: string, desc: string): void {
|
||||
const RESERVED = new Set(["wiki", "book-search", "book-import"]);
|
||||
|
||||
function domainSkill(key: string, n: number, title: string, desc: string): string {
|
||||
const brief = desc.replace(/"/g, "").replace(/。$/, "");
|
||||
const t = title.replace(/"/g, "");
|
||||
return `---
|
||||
name: ${key}
|
||||
allowed-tools: Bash(\${CLAUDE_PLUGIN_ROOT}/scripts/wiki.sh *)
|
||||
description: "查詢${t}的知識(${brief})。使用者執行 /jsc-wiki:${key} 或詢問與「${t}」相關的操作步驟時使用。"
|
||||
---
|
||||
|
||||
# JSC 知識庫・第${n}章 ${t}
|
||||
|
||||
目前章節內容(來自 wiki,唯讀):
|
||||
|
||||
!\`\${CLAUDE_PLUGIN_ROOT}/scripts/wiki.sh chapter ${n}\`
|
||||
|
||||
## 流程
|
||||
|
||||
0. 上方若顯示錯誤或沒有內容,先自行執行 \`\${CLAUDE_PLUGIN_ROOT}/scripts/wiki.sh chapter N\`(N 為本章號)。
|
||||
1. 使用者沒給主題(\`$ARGUMENTS\` 為空):只列出上面的篇目並詢問要看哪一篇,不要全文貼出。
|
||||
2. 有給主題:用 \`\${CLAUDE_PLUGIN_ROOT}/scripts/wiki.sh page <編號>\`(例如 \`${n}.1\`)讀取最相關的一到兩篇,依內容回答;找不到再用 \`wiki.sh search <關鍵字>\` 跨章搜尋。
|
||||
3. 只依 wiki 內容回答並註明頁面編號;wiki 沒寫的就說沒有,不要憑記憶補指令。
|
||||
4. 內容中 \`<密碼>\`、\`<Runner token>\` 等是占位符,不要猜測實際值;執行會改動系統的指令前先跟使用者確認。
|
||||
|
||||
回覆使用繁體中文(程式碼、指令除外)。
|
||||
`;
|
||||
}
|
||||
|
||||
/** 新增一章,並產生對應的領域技能(skills/<key>/SKILL.md),同步更新 README 表格與 wiki 技能的指令清單。 */
|
||||
function cmdAddChapter(args: string[]): void {
|
||||
const flag = (name: string): string | undefined => {
|
||||
const i = args.indexOf(name);
|
||||
return i >= 0 ? args[i + 1] : undefined;
|
||||
};
|
||||
const key = flag("--key") ?? die("缺少 --key <領域指令名稱>(英文小寫,例如 security)");
|
||||
const skillsDir = flag("--skills-dir") ?? join(dirname(process.argv[1]), "..", "skills");
|
||||
const pos = args.filter((a, i) => !a.startsWith("--") && !args[i - 1]?.startsWith("--"));
|
||||
if (pos.length !== 2) die("用法:add-chapter <標題> <說明> --key <名稱> [--skills-dir <目錄>]");
|
||||
const [title, desc] = pos;
|
||||
if (!/^[a-z][a-z0-9-]*$/.test(key)) die(`--key 只能用英文小寫、數字與連字號:${key}`);
|
||||
if (RESERVED.has(key)) die(`--key 不可使用保留名稱:${key}`);
|
||||
const skillFile = join(skillsDir, key, "SKILL.md");
|
||||
if (existsSync(skillFile)) die(`已有同名技能:${skillFile}`);
|
||||
sync();
|
||||
const n = Math.max(0, ...chapterFiles().map(([k]) => k)) + 1;
|
||||
const name = `第${n}章-${slug(title)}.md`;
|
||||
write(inWork(name), `# 第${n}章 ${title}\n\n${desc}\n`);
|
||||
makeIndex();
|
||||
console.log(`已新增:${name.slice(0, -3)}\n提醒:領域指令 /jsc-wiki:<領域> 需另外新增對應的技能(見 README)。`);
|
||||
|
||||
mkdirSync(dirname(skillFile), { recursive: true });
|
||||
write(skillFile, domainSkill(key, n, title, desc));
|
||||
const touched = [skillFile];
|
||||
|
||||
const readme = join(skillsDir, "..", "README.md");
|
||||
if (existsSync(readme)) {
|
||||
const lines = read(readme).split("\n");
|
||||
const last = lines.map((l) => l.startsWith("| `/jsc-wiki:")).lastIndexOf(true);
|
||||
if (last >= 0) {
|
||||
lines.splice(last + 1, 0, `| \`/jsc-wiki:${key}\` | ${n} ${title} | ${desc.replace(/。$/, "")} |`);
|
||||
write(readme, lines.join("\n"));
|
||||
touched.push(readme);
|
||||
}
|
||||
}
|
||||
const wikiSkill = join(skillsDir, "wiki", "SKILL.md");
|
||||
if (existsSync(wikiSkill)) {
|
||||
const lines = read(wikiSkill).split("\n");
|
||||
const i = lines.findIndex((l) => l.includes("各領域指令:"));
|
||||
if (i >= 0) {
|
||||
lines[i] = lines[i].replace(/。$/, `、\`:${key}\`。`);
|
||||
write(wikiSkill, lines.join("\n"));
|
||||
touched.push(wikiSkill);
|
||||
}
|
||||
}
|
||||
console.log(`已新增:${name.slice(0, -3)}(wiki 工作副本,尚未推送)`);
|
||||
console.log(`已產生領域技能 /jsc-wiki:${key},變更的檔案:\n${touched.map((f) => " " + f).join("\n")}`);
|
||||
console.log("提醒:技能檔在插件目錄,需 commit 進 jsc-marketplace repo 才會保留;重新載入插件後指令才會出現。");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- lint
|
||||
@@ -319,7 +389,7 @@ switch (cmd) {
|
||||
case "chapters": cmdChapters(); break;
|
||||
case "find": rest.length ? cmdFind(rest) : die("用法:find <關鍵字>..."); break;
|
||||
case "add": cmdAdd(rest); break;
|
||||
case "add-chapter": rest.length === 2 ? cmdAddChapter(rest[0], rest[1]) : die("用法:add-chapter <標題> <說明>"); break;
|
||||
case "add-chapter": cmdAddChapter(rest); break;
|
||||
case "index": sync(); makeIndex(); console.log("已重建章節頁、Home 目錄與上下頁導覽。"); break;
|
||||
case "lint": cmdLint(rest); break;
|
||||
case "diff": cmdDiff(); break;
|
||||
|
||||
Reference in New Issue
Block a user