@jungtz/wiki-router 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/dist/index.cjs +39 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +39 -1
- package/package.json +3 -2
- package/src/types.d.ts +1 -0
package/README.md
CHANGED
|
@@ -67,6 +67,7 @@ console.log(ctx)
|
|
|
67
67
|
| `outputDir` | `string` | ✅ | Wiki 輸出目錄 |
|
|
68
68
|
| `modelId` | `string` | | Wiki 生成模型,格式 `provider/model` |
|
|
69
69
|
| `routerModelId` | `string` | | 路由選擇模型,預設同 `modelId` |
|
|
70
|
+
| `timeout` | `number` | | LLM 對話逾時毫秒數,預設 `300000` (5 分鐘) |
|
|
70
71
|
|
|
71
72
|
|
|
72
73
|
### `wiki.build()`
|
|
@@ -117,6 +118,29 @@ my-project/
|
|
|
117
118
|
│ └── ...
|
|
118
119
|
```
|
|
119
120
|
|
|
121
|
+
## 互動預覽
|
|
122
|
+
|
|
123
|
+
內建互動式 TUI,可在終端直接問答測試 Wiki 路由效果:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
npm run preview
|
|
127
|
+
|
|
128
|
+
# 自訂路徑
|
|
129
|
+
npm run preview -- --knowledge ./my-knowledge --output ./my-wiki
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
支援指令:`:list` 查看維基頁面、`:build` 重建維基、`:files` 顯示檔案、`:quit` 離開。
|
|
133
|
+
|
|
134
|
+
## 發布腳本
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
npm run bump:patch # 版號 patch +1 並自動 git commit + tag
|
|
138
|
+
npm run bump:minor # 版號 minor +1
|
|
139
|
+
npm run bump:major # 版號 major +1
|
|
140
|
+
npm run push:version # 推送 commit 與 tag 至 remote
|
|
141
|
+
npm run release # bump:patch + push:version
|
|
142
|
+
```
|
|
143
|
+
|
|
120
144
|
## 錯誤處理
|
|
121
145
|
|
|
122
146
|
Wiki Router 採用靜默失敗策略:若模型設定錯誤或 provider 無法連線,只會輸出警告並回傳空內容,不會中斷主流程。
|
package/dist/index.cjs
CHANGED
|
@@ -266,6 +266,7 @@ function createWikiRouter(config) {
|
|
|
266
266
|
outputDir,
|
|
267
267
|
modelId,
|
|
268
268
|
routerModelId,
|
|
269
|
+
timeout = 300000,
|
|
269
270
|
} = config;
|
|
270
271
|
|
|
271
272
|
if (!router) throw new Error('[wiki-router] router is required')
|
|
@@ -275,14 +276,44 @@ function createWikiRouter(config) {
|
|
|
275
276
|
const resolvedKnowledgeDir = path.resolve(knowledgeDir);
|
|
276
277
|
const resolvedOutputDir = path.resolve(outputDir);
|
|
277
278
|
|
|
279
|
+
let modelsFetched = false;
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* 預先獲取本地模型清單(仿照 models.js 的 getModelsList 邏輯)
|
|
283
|
+
* 確保 switchModel 能識別動態發現的 local 模型
|
|
284
|
+
*/
|
|
285
|
+
async function ensureModels() {
|
|
286
|
+
if (modelsFetched) return
|
|
287
|
+
try {
|
|
288
|
+
const { models } = await router.getModels();
|
|
289
|
+
const localProviders = Object.keys(router.config.providers).filter(
|
|
290
|
+
p => router.config.providers[p].type === 'local'
|
|
291
|
+
);
|
|
292
|
+
localProviders.forEach(pName => {
|
|
293
|
+
const pModels = models.filter(m => m.provider === pName);
|
|
294
|
+
if (pModels.length > 0) {
|
|
295
|
+
router.config.providers[pName].models = pModels.map(m => ({
|
|
296
|
+
model: m.model,
|
|
297
|
+
description: m.description
|
|
298
|
+
}));
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
modelsFetched = true;
|
|
302
|
+
} catch (e) {
|
|
303
|
+
console.warn('[Wiki] Failed to fetch models:', e.message);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
278
307
|
/**
|
|
279
308
|
* 向 LLM 發送對話並取得完整回應
|
|
280
309
|
* @param {{ role: string, content: string }[]} messages
|
|
281
310
|
* @param {string} [overrideModelId]
|
|
311
|
+
* @param {number} [overrideTimeout]
|
|
282
312
|
* @returns {Promise<string|null>}
|
|
283
313
|
*/
|
|
284
|
-
async function chat(messages, overrideModelId) {
|
|
314
|
+
async function chat(messages, overrideModelId, overrideTimeout) {
|
|
285
315
|
const wikiModelId = overrideModelId || modelId || process.env.WIKI_MODEL || 'ollama-local/gemma4:31b';
|
|
316
|
+
const effectiveTimeout = overrideTimeout || timeout;
|
|
286
317
|
|
|
287
318
|
try {
|
|
288
319
|
let provider;
|
|
@@ -296,10 +327,17 @@ function createWikiRouter(config) {
|
|
|
296
327
|
|
|
297
328
|
// 使用 AI Router 進行對話
|
|
298
329
|
if (router && provider) {
|
|
330
|
+
await ensureModels();
|
|
299
331
|
await router.switchModel(provider, modelName);
|
|
300
332
|
let content = '';
|
|
301
333
|
const stream = router.chat(messages);
|
|
334
|
+
|
|
335
|
+
const deadline = Date.now() + effectiveTimeout;
|
|
302
336
|
for await (const chunk of stream) {
|
|
337
|
+
if (Date.now() > deadline) {
|
|
338
|
+
console.warn(`[Wiki Chat] Timeout after ${effectiveTimeout}ms`);
|
|
339
|
+
break
|
|
340
|
+
}
|
|
303
341
|
if (chunk.type === 'content') content += chunk.content;
|
|
304
342
|
}
|
|
305
343
|
return content
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @property {string} outputDir - 輸出 Wiki 檔案的目錄路徑 (required)
|
|
10
10
|
* @property {string} [modelId] - Wiki 生成使用的模型 ID,格式: 'provider/model'
|
|
11
11
|
* @property {string} [routerModelId] - 路由選擇使用的模型 ID,預設同 modelId
|
|
12
|
+
* @property {number} [timeout=300000] - 每次 LLM 對話的逾時毫秒數
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -264,6 +264,7 @@ function createWikiRouter(config) {
|
|
|
264
264
|
outputDir,
|
|
265
265
|
modelId,
|
|
266
266
|
routerModelId,
|
|
267
|
+
timeout = 300000,
|
|
267
268
|
} = config;
|
|
268
269
|
|
|
269
270
|
if (!router) throw new Error('[wiki-router] router is required')
|
|
@@ -273,14 +274,44 @@ function createWikiRouter(config) {
|
|
|
273
274
|
const resolvedKnowledgeDir = path.resolve(knowledgeDir);
|
|
274
275
|
const resolvedOutputDir = path.resolve(outputDir);
|
|
275
276
|
|
|
277
|
+
let modelsFetched = false;
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* 預先獲取本地模型清單(仿照 models.js 的 getModelsList 邏輯)
|
|
281
|
+
* 確保 switchModel 能識別動態發現的 local 模型
|
|
282
|
+
*/
|
|
283
|
+
async function ensureModels() {
|
|
284
|
+
if (modelsFetched) return
|
|
285
|
+
try {
|
|
286
|
+
const { models } = await router.getModels();
|
|
287
|
+
const localProviders = Object.keys(router.config.providers).filter(
|
|
288
|
+
p => router.config.providers[p].type === 'local'
|
|
289
|
+
);
|
|
290
|
+
localProviders.forEach(pName => {
|
|
291
|
+
const pModels = models.filter(m => m.provider === pName);
|
|
292
|
+
if (pModels.length > 0) {
|
|
293
|
+
router.config.providers[pName].models = pModels.map(m => ({
|
|
294
|
+
model: m.model,
|
|
295
|
+
description: m.description
|
|
296
|
+
}));
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
modelsFetched = true;
|
|
300
|
+
} catch (e) {
|
|
301
|
+
console.warn('[Wiki] Failed to fetch models:', e.message);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
276
305
|
/**
|
|
277
306
|
* 向 LLM 發送對話並取得完整回應
|
|
278
307
|
* @param {{ role: string, content: string }[]} messages
|
|
279
308
|
* @param {string} [overrideModelId]
|
|
309
|
+
* @param {number} [overrideTimeout]
|
|
280
310
|
* @returns {Promise<string|null>}
|
|
281
311
|
*/
|
|
282
|
-
async function chat(messages, overrideModelId) {
|
|
312
|
+
async function chat(messages, overrideModelId, overrideTimeout) {
|
|
283
313
|
const wikiModelId = overrideModelId || modelId || process.env.WIKI_MODEL || 'ollama-local/gemma4:31b';
|
|
314
|
+
const effectiveTimeout = overrideTimeout || timeout;
|
|
284
315
|
|
|
285
316
|
try {
|
|
286
317
|
let provider;
|
|
@@ -294,10 +325,17 @@ function createWikiRouter(config) {
|
|
|
294
325
|
|
|
295
326
|
// 使用 AI Router 進行對話
|
|
296
327
|
if (router && provider) {
|
|
328
|
+
await ensureModels();
|
|
297
329
|
await router.switchModel(provider, modelName);
|
|
298
330
|
let content = '';
|
|
299
331
|
const stream = router.chat(messages);
|
|
332
|
+
|
|
333
|
+
const deadline = Date.now() + effectiveTimeout;
|
|
300
334
|
for await (const chunk of stream) {
|
|
335
|
+
if (Date.now() > deadline) {
|
|
336
|
+
console.warn(`[Wiki Chat] Timeout after ${effectiveTimeout}ms`);
|
|
337
|
+
break
|
|
338
|
+
}
|
|
301
339
|
if (chunk.type === 'content') content += chunk.content;
|
|
302
340
|
}
|
|
303
341
|
return content
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jungtz/wiki-router",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "LLM Wiki 知識庫路由引擎 - 將結構化知識轉為 Markdown 維基,智慧路由查詢",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"build:prod": "cross-env NODE_ENV=production rollup -c",
|
|
34
34
|
"dev": "rollup -c -w",
|
|
35
35
|
"test": "node --test",
|
|
36
|
+
"preview": "node scripts/preview.js",
|
|
36
37
|
"lint": "eslint src/",
|
|
37
38
|
"lint:fix": "eslint src/ --fix",
|
|
38
39
|
"format": "prettier --write src/",
|
|
@@ -55,7 +56,6 @@
|
|
|
55
56
|
"ai"
|
|
56
57
|
],
|
|
57
58
|
"license": "MIT",
|
|
58
|
-
"dependencies": {},
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"@jungtz/ai-router": "^1.0.0"
|
|
61
61
|
},
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
}
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
+
"@jungtz/ai-router": "^1.0.23",
|
|
68
69
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
69
70
|
"cross-env": "^10.1.0",
|
|
70
71
|
"eslint": "^8.57.0",
|
package/src/types.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @property {string} outputDir - 輸出 Wiki 檔案的目錄路徑 (required)
|
|
10
10
|
* @property {string} [modelId] - Wiki 生成使用的模型 ID,格式: 'provider/model'
|
|
11
11
|
* @property {string} [routerModelId] - 路由選擇使用的模型 ID,預設同 modelId
|
|
12
|
+
* @property {number} [timeout=300000] - 每次 LLM 對話的逾時毫秒數
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
/**
|