@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 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.1",
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
  /**