Skip to content

Commit 90a44d7

Browse files
committed
feat: llm wiki sync
1 parent d08edf0 commit 90a44d7

3 files changed

Lines changed: 277 additions & 50 deletions

File tree

packages/cli/postinstall.js

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@
55
* 保证用户首次使用 `bl advisor recommend` 时数据已就位。
66
*
77
* 流程:
8-
* 1. fetch FC 签名函数 → 拿 OSS 预签名 URL
9-
* 2. 下载 manifest.json + wiki-doc-full.tar.br(~2.15MB)
10-
* 3. 校验 sha256
11-
* 4. Node 原生 brotli 解压 + tar-stream 解包到同盘临时目录
12-
* 5. renameSync 原子替换到 ~/.bailian/skills/bailian-docs-llm-wiki/
13-
* 6. 写 ~/.bailian/wiki-sync-state.json
8+
* 1. 从公共读 OSS 直链下载 manifest.json + wiki-doc-full.tar.br(~2.15MB)
9+
* 2. 校验 sha256
10+
* 3. Node 原生 brotli 解压 + tar-stream 解包到同盘临时目录
11+
* 4. renameSync 原子替换到 ~/.bailian/skills/bailian-docs-llm-wiki/
12+
* 5. 写 ~/.bailian/wiki-sync-state.json
1413
*
1514
* 设计约束:
1615
* - 无条件覆盖:每次 install 都全量替换,不比对已有版本
@@ -34,7 +33,7 @@ import { pipeline } from "node:stream/promises";
3433
import { createBrotliDecompress } from "node:zlib";
3534
import tar from "tar-stream";
3635

37-
const FC_SIGN_URL = "https://signature-gmqkxxozrl.cn-hangzhou.fcapp.run";
36+
const OSS_BASE_URL = "https://bailian-wiki.oss-cn-hangzhou.aliyuncs.com/bailian-docs-llm-wiki";
3837
const CONFIG_DIR_NAME = ".bailian";
3938
const SKILL_DIR_NAME = "skills/bailian-docs-llm-wiki";
4039
const STATE_FILE_NAME = "wiki-sync-state.json";
@@ -106,25 +105,18 @@ function atomicSwap(tmpDir, catalogDir) {
106105
}
107106

108107
async function main() {
109-
// 1. 拿全部签名 URL
110-
const signResp = await fetchJson(FC_SIGN_URL, MANIFEST_TIMEOUT_MS);
111-
const urls = signResp?.urls;
112-
if (!urls?.[MANIFEST_KEY] || !urls?.[ASSET_KEY]) {
113-
throw new Error("签名函数未返回所需 URL");
114-
}
115-
116-
// 2. 下载 manifest
117-
const manifest = await fetchJson(urls[MANIFEST_KEY], MANIFEST_TIMEOUT_MS);
108+
// 1. 下载 manifest
109+
const manifest = await fetchJson(`${OSS_BASE_URL}/${MANIFEST_KEY}`, MANIFEST_TIMEOUT_MS);
118110
if (!manifest?.version) throw new Error("manifest 无 version");
119111

120-
// 3. 下载 tar.br + 校验
121-
const tarBuf = await downloadBuffer(urls[ASSET_KEY]);
112+
// 2. 下载 tar.br + 校验
113+
const tarBuf = await downloadBuffer(`${OSS_BASE_URL}/${ASSET_KEY}`);
122114
const sha256 = createHash("sha256").update(tarBuf).digest("hex");
123115
if (manifest.asset?.sha256 && sha256 !== manifest.asset.sha256) {
124116
throw new Error("sha256 校验失败");
125117
}
126118

127-
// 4. 解包到同盘临时目录 + 原子替换
119+
// 3. 解包到同盘临时目录 + 原子替换
128120
const catalogDir = getCatalogDir();
129121
const tmpDir = `${catalogDir}.tmp-${process.pid}-${Date.now()}`;
130122
try {
@@ -136,7 +128,7 @@ async function main() {
136128
throw err;
137129
}
138130

139-
// 5. 写 state
131+
// 4. 写 state
140132
try {
141133
writeFileSync(
142134
getStatePath(),

packages/core/src/advisor/sync.ts

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* `bl advisor recommend` 执行时调用 `maybeSyncWikiData()`:
55
* 1. 12h throttle:距上次检查不足 12h 直接跳过
6-
* 2. 拉 FC 签名 URL → 下载 manifest.json 比对版本
6+
* 2. 从公共读 OSS 下载 manifest.json 比对版本
77
* 3. 版本相同 → 仅刷新 lastChecked
88
* 4. 版本不同 → 下载 tar.br → 校验 sha256 → brotli 解压 + tar-stream 解包
99
* 到同盘临时目录 → renameSync 原子替换 → 写 state
@@ -30,8 +30,8 @@ import { createBrotliDecompress } from "node:zlib";
3030
import tar from "tar-stream";
3131
import { getConfigDir } from "../config/paths.ts";
3232

33-
/** FC 匿名签名函数入口,返回 OSS 预签名 URL(硬编码,不走 env)。 */
34-
const FC_SIGN_URL = "https://signature-gmqkxxozrl.cn-hangzhou.fcapp.run";
33+
/** 公共读 OSS 目录,直链下载(硬编码,不走 env)。 */
34+
const OSS_BASE_URL = "https://bailian-wiki.oss-cn-hangzhou.aliyuncs.com/bailian-docs-llm-wiki";
3535
const SKILL_DIR_NAME = "skills/bailian-docs-llm-wiki";
3636
const STATE_FILE_NAME = "wiki-sync-state.json";
3737
const MODELS_FILE = "models.jsonl";
@@ -93,20 +93,6 @@ function writeState(state: SyncState): void {
9393
}
9494
}
9595

96-
/** 拉全部 OSS 预签名 URL:`{ urls: { "manifest.json": "...", "wiki-doc-full.tar.br": "..." } }` */
97-
async function fetchSignedUrls(): Promise<Record<string, string> | null> {
98-
try {
99-
const res = await fetch(FC_SIGN_URL, {
100-
signal: AbortSignal.timeout(MANIFEST_TIMEOUT_MS),
101-
});
102-
if (!res.ok) return null;
103-
const data = (await res.json()) as { urls?: Record<string, string> };
104-
return data.urls ?? null;
105-
} catch {
106-
return null;
107-
}
108-
}
109-
11096
async function fetchManifest(url: string): Promise<Manifest | null> {
11197
try {
11298
const res = await fetch(url, { signal: AbortSignal.timeout(MANIFEST_TIMEOUT_MS) });
@@ -182,25 +168,23 @@ export async function maybeSyncWikiData(): Promise<boolean> {
182168
return false;
183169
}
184170

185-
// 2. 拿签名 URL + manifest
186-
const urls = await fetchSignedUrls();
187-
if (!urls?.[MANIFEST_KEY]) return false; // 失败不写 lastChecked,下次重试
188-
189-
const manifest = await fetchManifest(urls[MANIFEST_KEY]);
190-
if (!manifest?.version) return false;
171+
// 2. 拉 manifest
172+
const manifest = await fetchManifest(`${OSS_BASE_URL}/${MANIFEST_KEY}`);
173+
if (!manifest?.version) return false; // 失败不写 lastChecked,下次重试
191174

192175
// 3. 版本相同且本地数据存在:仅刷新 lastChecked,无需重新下载。
193-
// 若数据缺失,即便版本相同也要继续走下载补齐(落到第 4 步)。
194-
if (state && manifest.version === state.version && catalogDataExists()) {
195-
writeState({ lastChecked: now, version: state.version });
176+
// 覆盖两种状态:(a) state.version === manifest.version → 直接命中;
177+
// (b) state 缺失但数据完好(用户或意外只删了 state)→ 用 manifest 版本
178+
// 写回 state,避免无谓的 2MB 下载+解压。
179+
// 数据缺失或版本落后时落到第 4 步全量下载补齐。
180+
const dataOk = catalogDataExists();
181+
if (dataOk && (!state || state.version === manifest.version)) {
182+
writeState({ lastChecked: now, version: manifest.version });
196183
return false;
197184
}
198185

199186
// 4. 版本不同:下载 + 校验 + 解包 + 原子替换
200-
const assetUrl = urls[ASSET_KEY];
201-
if (!assetUrl) return false;
202-
203-
const tarBuf = await downloadBuffer(assetUrl);
187+
const tarBuf = await downloadBuffer(`${OSS_BASE_URL}/${ASSET_KEY}`);
204188
if (!tarBuf) return false;
205189

206190
// sha256 校验

skills-lock.json

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
{
2+
"version": 1,
3+
"skills": {
4+
"ask-matt": {
5+
"source": "mattpocock/skills",
6+
"sourceType": "github",
7+
"skillPath": "skills/engineering/ask-matt/SKILL.md",
8+
"computedHash": "0f843160e34a24f5bd12cdc7de7d40951e77fbdc05ce8f891b37ca32eac2c44d"
9+
},
10+
"batch-grill-me": {
11+
"source": "mattpocock/skills",
12+
"sourceType": "github",
13+
"skillPath": "skills/in-progress/batch-grill-me/SKILL.md",
14+
"computedHash": "f448831b8f04518b1527408f1d5024384ad5f543bdbaac6fabb7aa053ad60489"
15+
},
16+
"claude-handoff": {
17+
"source": "mattpocock/skills",
18+
"sourceType": "github",
19+
"skillPath": "skills/in-progress/claude-handoff/SKILL.md",
20+
"computedHash": "40a7f4ec80b9826ad7d0c47b0778c99686d6d9d662112b3e175a816f3aca4c39"
21+
},
22+
"code-review": {
23+
"source": "mattpocock/skills",
24+
"sourceType": "github",
25+
"skillPath": "skills/engineering/code-review/SKILL.md",
26+
"computedHash": "31d149a480eaa68c11e32f5ee77f0fd0b98a906834d531d881d502352edd0b8e"
27+
},
28+
"codebase-design": {
29+
"source": "mattpocock/skills",
30+
"sourceType": "github",
31+
"skillPath": "skills/engineering/codebase-design/SKILL.md",
32+
"computedHash": "6d9d51d8caa01633fd00cf87089c5618c982321f942ac69f62565dc001c6b22f"
33+
},
34+
"design-an-interface": {
35+
"source": "mattpocock/skills",
36+
"sourceType": "github",
37+
"skillPath": "skills/deprecated/design-an-interface/SKILL.md",
38+
"computedHash": "aef348a9af675b771635623b5aa7790da4d40adc1ee88b58b6fd116eda2047d8"
39+
},
40+
"diagnosing-bugs": {
41+
"source": "mattpocock/skills",
42+
"sourceType": "github",
43+
"skillPath": "skills/engineering/diagnosing-bugs/SKILL.md",
44+
"computedHash": "fd6c99466b7ba43be624e6e66ed6d7af2796ded7218f24c83820823977819e22"
45+
},
46+
"domain-modeling": {
47+
"source": "mattpocock/skills",
48+
"sourceType": "github",
49+
"skillPath": "skills/engineering/domain-modeling/SKILL.md",
50+
"computedHash": "363cb0f53b0b431e7c00086ad1f823500b7e1b70b5616ee969c979f0934e9e6e"
51+
},
52+
"edit-article": {
53+
"source": "mattpocock/skills",
54+
"sourceType": "github",
55+
"skillPath": "skills/personal/edit-article/SKILL.md",
56+
"computedHash": "cb2a13b2acb6c8a0706eb3a973a2681f30fd74c00784c74ceaa98e12eb2b2fc3"
57+
},
58+
"git-guardrails-claude-code": {
59+
"source": "mattpocock/skills",
60+
"sourceType": "github",
61+
"skillPath": "skills/misc/git-guardrails-claude-code/SKILL.md",
62+
"computedHash": "8c29552c621da0121427306afd92f8e02f47f446cdb0b55ceae01de6879fcb3a"
63+
},
64+
"grill-me": {
65+
"source": "mattpocock/skills",
66+
"sourceType": "github",
67+
"skillPath": "skills/productivity/grill-me/SKILL.md",
68+
"computedHash": "f361db4e15e6bfd562a9282b1dccda513910a50061f9e838ce017be9c69dde3f"
69+
},
70+
"grill-with-docs": {
71+
"source": "mattpocock/skills",
72+
"sourceType": "github",
73+
"skillPath": "skills/engineering/grill-with-docs/SKILL.md",
74+
"computedHash": "9c460cbd94fd3c63cdef967dbdb6e66ca687103cdc380cd37834e4d10b738f78"
75+
},
76+
"grilling": {
77+
"source": "mattpocock/skills",
78+
"sourceType": "github",
79+
"skillPath": "skills/productivity/grilling/SKILL.md",
80+
"computedHash": "368d3dd7251247c69f3656d93dc83c8f1577792eacac2111f1e7981db2ece49b"
81+
},
82+
"handoff": {
83+
"source": "mattpocock/skills",
84+
"sourceType": "github",
85+
"skillPath": "skills/productivity/handoff/SKILL.md",
86+
"computedHash": "ad03e8d4ea3cbbff66420eb7ba3cc375b5cbe1821a2449b53e863256cf5b5cde"
87+
},
88+
"implement": {
89+
"source": "mattpocock/skills",
90+
"sourceType": "github",
91+
"skillPath": "skills/engineering/implement/SKILL.md",
92+
"computedHash": "2139cfedf24791adbc839aaab6019cff158af1e28bfead020ec6e0ce01b3e74d"
93+
},
94+
"improve-codebase-architecture": {
95+
"source": "mattpocock/skills",
96+
"sourceType": "github",
97+
"skillPath": "skills/engineering/improve-codebase-architecture/SKILL.md",
98+
"computedHash": "66e8a50c83c3c724fcfe0769701b665c56cec220cc4f49cc1aee8bdfc07de94a"
99+
},
100+
"loop-me": {
101+
"source": "mattpocock/skills",
102+
"sourceType": "github",
103+
"skillPath": "skills/in-progress/loop-me/SKILL.md",
104+
"computedHash": "e1fcab9b531b338eb540c9d57ee089e2660e4bba1d7623ec566c6f32f77f2d26"
105+
},
106+
"migrate-to-shoehorn": {
107+
"source": "mattpocock/skills",
108+
"sourceType": "github",
109+
"skillPath": "skills/misc/migrate-to-shoehorn/SKILL.md",
110+
"computedHash": "6397731ced114f3657aa88b55ed13d1344a56d77ca449c568e3200c21740fa99"
111+
},
112+
"obsidian-vault": {
113+
"source": "mattpocock/skills",
114+
"sourceType": "github",
115+
"skillPath": "skills/personal/obsidian-vault/SKILL.md",
116+
"computedHash": "5c08eda96fd76a71793c0a8cb91bef41d518586654a14af4f2edf8f8fd0f96a7"
117+
},
118+
"prototype": {
119+
"source": "mattpocock/skills",
120+
"sourceType": "github",
121+
"skillPath": "skills/engineering/prototype/SKILL.md",
122+
"computedHash": "faba901c53a6ca245174c4ba5db3929d14253232b3050fdbd46539720adf1ab8"
123+
},
124+
"qa": {
125+
"source": "mattpocock/skills",
126+
"sourceType": "github",
127+
"skillPath": "skills/deprecated/qa/SKILL.md",
128+
"computedHash": "223de2b02aa9ab36cfa4fe93e80e527b56e912e7ae725f9d596f6d2457afab77"
129+
},
130+
"request-refactor-plan": {
131+
"source": "mattpocock/skills",
132+
"sourceType": "github",
133+
"skillPath": "skills/deprecated/request-refactor-plan/SKILL.md",
134+
"computedHash": "08c06e587d0f979b8731f6a00c67fb8d00e563614daf80bf648d41148e553473"
135+
},
136+
"research": {
137+
"source": "mattpocock/skills",
138+
"sourceType": "github",
139+
"skillPath": "skills/engineering/research/SKILL.md",
140+
"computedHash": "bd3e2c6826671d82c86ed0da3dac3370ebcf63b0fe847f91bb444e1fb7dac21b"
141+
},
142+
"resolving-merge-conflicts": {
143+
"source": "mattpocock/skills",
144+
"sourceType": "github",
145+
"skillPath": "skills/engineering/resolving-merge-conflicts/SKILL.md",
146+
"computedHash": "28aad6f8b1b7025abc8892fa8890f68fe1533499b28a565f416b159131d22fad"
147+
},
148+
"scaffold-exercises": {
149+
"source": "mattpocock/skills",
150+
"sourceType": "github",
151+
"skillPath": "skills/misc/scaffold-exercises/SKILL.md",
152+
"computedHash": "354c91f6dbc9b058632f30594aacb4edc6d25012596585abb00402af8d7ec5e9"
153+
},
154+
"setup-matt-pocock-skills": {
155+
"source": "mattpocock/skills",
156+
"sourceType": "github",
157+
"skillPath": "skills/engineering/setup-matt-pocock-skills/SKILL.md",
158+
"computedHash": "74e894a3509e2676d4cdb771c8eace087092430635e845e02a9cc2f757c552a4"
159+
},
160+
"setup-pre-commit": {
161+
"source": "mattpocock/skills",
162+
"sourceType": "github",
163+
"skillPath": "skills/misc/setup-pre-commit/SKILL.md",
164+
"computedHash": "1b140af948d0a6330c4cf52d46ca2e06a0e96fdc34d22ec8888d2b9751b99b62"
165+
},
166+
"setup-ts-deep-modules": {
167+
"source": "mattpocock/skills",
168+
"sourceType": "github",
169+
"skillPath": "skills/in-progress/setup-ts-deep-modules/SKILL.md",
170+
"computedHash": "bd5cbaa455454c2d6c27a1b734e0d820606da6c482bf3c79ec55fbc3f3e03ef3"
171+
},
172+
"tdd": {
173+
"source": "mattpocock/skills",
174+
"sourceType": "github",
175+
"skillPath": "skills/engineering/tdd/SKILL.md",
176+
"computedHash": "81eca2a5b53a63f481c0849be7a663a8cd43d5cf53f32b644ec0a2f50cf91aa2"
177+
},
178+
"teach": {
179+
"source": "mattpocock/skills",
180+
"sourceType": "github",
181+
"skillPath": "skills/productivity/teach/SKILL.md",
182+
"computedHash": "68999bb1a241384b2f921f3321d779b7d05eb6089077b70d88cee2aee3d75ccc"
183+
},
184+
"to-questionnaire": {
185+
"source": "mattpocock/skills",
186+
"sourceType": "github",
187+
"skillPath": "skills/in-progress/to-questionnaire/SKILL.md",
188+
"computedHash": "d8938509f3400d9977343e11e876fc6e1982b0b9c133a2f2e9d3d730a67a103e"
189+
},
190+
"to-spec": {
191+
"source": "mattpocock/skills",
192+
"sourceType": "github",
193+
"skillPath": "skills/engineering/to-spec/SKILL.md",
194+
"computedHash": "0f544cd0c099c06f0dd0b7b9ee98b4237218e7e95fd3d3c02e791efbaf74bacb"
195+
},
196+
"to-tickets": {
197+
"source": "mattpocock/skills",
198+
"sourceType": "github",
199+
"skillPath": "skills/engineering/to-tickets/SKILL.md",
200+
"computedHash": "5d79577541b5cf6dade61c69844432ea20ce7b12527cdda1dd4d6fe8d59a135d"
201+
},
202+
"triage": {
203+
"source": "mattpocock/skills",
204+
"sourceType": "github",
205+
"skillPath": "skills/engineering/triage/SKILL.md",
206+
"computedHash": "7c923b6a677cfe689500721f08307e2a4c46797ff169dc55ef6c34a431a0d533"
207+
},
208+
"ubiquitous-language": {
209+
"source": "mattpocock/skills",
210+
"sourceType": "github",
211+
"skillPath": "skills/deprecated/ubiquitous-language/SKILL.md",
212+
"computedHash": "0395170031b57ea63f2eb22561542894c03e3047430a2f1118a06b411054429b"
213+
},
214+
"wayfinder": {
215+
"source": "mattpocock/skills",
216+
"sourceType": "github",
217+
"skillPath": "skills/engineering/wayfinder/SKILL.md",
218+
"computedHash": "c9e18cefd77b6b5b0ee35f59ce2fd96359aa2d2f02e3479e12c873c5402d9d43"
219+
},
220+
"wizard": {
221+
"source": "mattpocock/skills",
222+
"sourceType": "github",
223+
"skillPath": "skills/in-progress/wizard/SKILL.md",
224+
"computedHash": "dab67fb9fdcc70f3a06cf2facecf58f405f478504812103b53d4c5a84765254d"
225+
},
226+
"writing-beats": {
227+
"source": "mattpocock/skills",
228+
"sourceType": "github",
229+
"skillPath": "skills/in-progress/writing-beats/SKILL.md",
230+
"computedHash": "7581e49a991e45e4e486b128c6391b82bd112c143cea3cc4426c23530dd545af"
231+
},
232+
"writing-fragments": {
233+
"source": "mattpocock/skills",
234+
"sourceType": "github",
235+
"skillPath": "skills/in-progress/writing-fragments/SKILL.md",
236+
"computedHash": "972ab831c7a39dab971439fa4718b668114d3063d347d8ba29b2a19765b3f911"
237+
},
238+
"writing-great-skills": {
239+
"source": "mattpocock/skills",
240+
"sourceType": "github",
241+
"skillPath": "skills/productivity/writing-great-skills/SKILL.md",
242+
"computedHash": "4deb21855fb4deeeb1b8217b041faff003fd0c915d24a22f636851c520bc9c5c"
243+
},
244+
"writing-shape": {
245+
"source": "mattpocock/skills",
246+
"sourceType": "github",
247+
"skillPath": "skills/in-progress/writing-shape/SKILL.md",
248+
"computedHash": "90899c7b3853a80da0d9ef634844b22871cc3ea6aa1bc9e4299f40484ac05392"
249+
}
250+
}
251+
}

0 commit comments

Comments
 (0)