@jungtz/wiki-router 1.2.0 → 1.3.0

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/dist/index.cjs CHANGED
@@ -282,6 +282,15 @@ function createWikiRouter(config) {
282
282
  }
283
283
  }
284
284
 
285
+ function formatElapsed(startMs) {
286
+ const ms = Date.now() - startMs;
287
+ if (ms < 1000) return `${ms}ms`
288
+ if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`
289
+ const m = Math.floor(ms / 60000);
290
+ const s = ((ms % 60000) / 1000).toFixed(1);
291
+ return `${m}m${s}s`
292
+ }
293
+
285
294
  function fingerprintsEqual(a, b) {
286
295
  if (!a || !b) return false
287
296
  const ak = Object.keys(a);
@@ -292,6 +301,7 @@ function createWikiRouter(config) {
292
301
 
293
302
  async function build(options = {}) {
294
303
  const { force = false } = options;
304
+ const buildStart = Date.now();
295
305
  try {
296
306
  const knowledgeKeys = await activeSource.list();
297
307
 
@@ -312,7 +322,7 @@ function createWikiRouter(config) {
312
322
  const storedFp = await activeStore.readManifest();
313
323
  const existingFiles = await activeStore.list();
314
324
  if (existingFiles.length > 0 && fingerprintsEqual(currentFp, storedFp)) {
315
- console.log('[Wiki] Source unchanged, skipping build (fingerprint match)');
325
+ console.log(`[Wiki] Source unchanged, skipping build (fingerprint match) — ${formatElapsed(buildStart)}`);
316
326
  return true
317
327
  }
318
328
  }
@@ -321,6 +331,7 @@ function createWikiRouter(config) {
321
331
  let totalFiles = 0;
322
332
 
323
333
  for (const key of knowledgeKeys) {
334
+ const keyStart = Date.now();
324
335
  const existingFiles = await activeStore.list();
325
336
  const isFirstTime = existingFiles.length === 0;
326
337
  const { type: fileType, content: fileContent } = await activeSource.read(key);
@@ -341,7 +352,7 @@ function createWikiRouter(config) {
341
352
 
342
353
  const output = await chat([{ role: 'user', content: finalPrompt }]);
343
354
  if (!output) {
344
- console.warn(`[Wiki] No output for: ${key}`);
355
+ console.warn(`[Wiki] No output for: ${key} — ${formatElapsed(keyStart)}`);
345
356
  continue
346
357
  }
347
358
 
@@ -356,17 +367,22 @@ function createWikiRouter(config) {
356
367
  console.log(`[Wiki] ${isFirstTime ? 'Generated' : 'Updated'}: ${filename}`);
357
368
  }
358
369
  totalFiles += parsed.length;
370
+ console.log(`[Wiki] Done: ${key} — ${parsed.length} file(s), ${formatElapsed(keyStart)}`);
359
371
  }
360
372
 
361
- if (totalFiles === 0) return false
373
+ if (totalFiles === 0) {
374
+ console.warn(`[Wiki] Build produced no files — ${formatElapsed(buildStart)}`);
375
+ return false
376
+ }
362
377
 
363
378
  if (currentFp && storeSupportsManifest) {
364
379
  await activeStore.writeManifest(currentFp);
365
380
  }
366
381
 
382
+ console.log(`[Wiki] Build complete — ${totalFiles} file(s), ${formatElapsed(buildStart)}`);
367
383
  return true
368
384
  } catch (err) {
369
- console.error('[Wiki Generation Error]', err);
385
+ console.error(`[Wiki Generation Error] (after ${formatElapsed(buildStart)})`, err);
370
386
  return false
371
387
  }
372
388
  }
@@ -549,6 +565,15 @@ function sqliteStore(config) {
549
565
 
550
566
  const DEFAULT_AUTO_INDEX_HEADER = '# 知識庫目錄';
551
567
 
568
+ function formatElapsed(startMs) {
569
+ const ms = Date.now() - startMs;
570
+ if (ms < 1000) return `${ms}ms`
571
+ if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`
572
+ const m = Math.floor(ms / 60000);
573
+ const s = ((ms % 60000) / 1000).toFixed(1);
574
+ return `${m}m${s}s`
575
+ }
576
+
552
577
  /**
553
578
  * @param {import('./types').TenantManagerConfig} config
554
579
  * @returns {import('./types').TenantManager}
@@ -610,10 +635,14 @@ function createTenantManager(config) {
610
635
  const { force = false } = options;
611
636
  if (buildPromises.has(tenantId)) return buildPromises.get(tenantId)
612
637
 
638
+ const tenantStart = Date.now();
613
639
  const promise = (async () => {
614
640
  const { wiki, store } = getWiki(tenantId);
615
641
  const ok = await wiki.build({ force });
616
- if (!ok) return false
642
+ if (!ok) {
643
+ logger.warn && logger.warn(`[Wiki] Tenant "${tenantId}" build failed — ${formatElapsed(tenantStart)}`);
644
+ return false
645
+ }
617
646
 
618
647
  if (autoIndex) {
619
648
  const hasIndex = await store.read('Index.md');
@@ -624,6 +653,7 @@ function createTenantManager(config) {
624
653
  }
625
654
 
626
655
  builtTenants.add(tenantId);
656
+ logger.log && logger.log(`[Wiki] Tenant "${tenantId}" ready — ${formatElapsed(tenantStart)}`);
627
657
  return true
628
658
  })().finally(() => {
629
659
  buildPromises.delete(tenantId);
@@ -642,8 +672,11 @@ function createTenantManager(config) {
642
672
  logger.log && logger.log('[Wiki] No tenants to build');
643
673
  return []
644
674
  }
675
+ const allStart = Date.now();
645
676
  logger.log && logger.log(`[Wiki] Pre-building ${tenants.length} tenant(s): ${tenants.join(', ')}`);
646
677
  const results = await Promise.allSettled(tenants.map(t => build(t)));
678
+ const okCount = results.filter(r => r.status === 'fulfilled' && r.value === true).length;
679
+ logger.log && logger.log(`[Wiki] buildAll done — ${okCount}/${tenants.length} ok, ${formatElapsed(allStart)}`);
647
680
  results.forEach((r, i) => {
648
681
  if (r.status === 'rejected') {
649
682
  logger.error && logger.error(
package/dist/index.mjs CHANGED
@@ -280,6 +280,15 @@ function createWikiRouter(config) {
280
280
  }
281
281
  }
282
282
 
283
+ function formatElapsed(startMs) {
284
+ const ms = Date.now() - startMs;
285
+ if (ms < 1000) return `${ms}ms`
286
+ if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`
287
+ const m = Math.floor(ms / 60000);
288
+ const s = ((ms % 60000) / 1000).toFixed(1);
289
+ return `${m}m${s}s`
290
+ }
291
+
283
292
  function fingerprintsEqual(a, b) {
284
293
  if (!a || !b) return false
285
294
  const ak = Object.keys(a);
@@ -290,6 +299,7 @@ function createWikiRouter(config) {
290
299
 
291
300
  async function build(options = {}) {
292
301
  const { force = false } = options;
302
+ const buildStart = Date.now();
293
303
  try {
294
304
  const knowledgeKeys = await activeSource.list();
295
305
 
@@ -310,7 +320,7 @@ function createWikiRouter(config) {
310
320
  const storedFp = await activeStore.readManifest();
311
321
  const existingFiles = await activeStore.list();
312
322
  if (existingFiles.length > 0 && fingerprintsEqual(currentFp, storedFp)) {
313
- console.log('[Wiki] Source unchanged, skipping build (fingerprint match)');
323
+ console.log(`[Wiki] Source unchanged, skipping build (fingerprint match) — ${formatElapsed(buildStart)}`);
314
324
  return true
315
325
  }
316
326
  }
@@ -319,6 +329,7 @@ function createWikiRouter(config) {
319
329
  let totalFiles = 0;
320
330
 
321
331
  for (const key of knowledgeKeys) {
332
+ const keyStart = Date.now();
322
333
  const existingFiles = await activeStore.list();
323
334
  const isFirstTime = existingFiles.length === 0;
324
335
  const { type: fileType, content: fileContent } = await activeSource.read(key);
@@ -339,7 +350,7 @@ function createWikiRouter(config) {
339
350
 
340
351
  const output = await chat([{ role: 'user', content: finalPrompt }]);
341
352
  if (!output) {
342
- console.warn(`[Wiki] No output for: ${key}`);
353
+ console.warn(`[Wiki] No output for: ${key} — ${formatElapsed(keyStart)}`);
343
354
  continue
344
355
  }
345
356
 
@@ -354,17 +365,22 @@ function createWikiRouter(config) {
354
365
  console.log(`[Wiki] ${isFirstTime ? 'Generated' : 'Updated'}: ${filename}`);
355
366
  }
356
367
  totalFiles += parsed.length;
368
+ console.log(`[Wiki] Done: ${key} — ${parsed.length} file(s), ${formatElapsed(keyStart)}`);
357
369
  }
358
370
 
359
- if (totalFiles === 0) return false
371
+ if (totalFiles === 0) {
372
+ console.warn(`[Wiki] Build produced no files — ${formatElapsed(buildStart)}`);
373
+ return false
374
+ }
360
375
 
361
376
  if (currentFp && storeSupportsManifest) {
362
377
  await activeStore.writeManifest(currentFp);
363
378
  }
364
379
 
380
+ console.log(`[Wiki] Build complete — ${totalFiles} file(s), ${formatElapsed(buildStart)}`);
365
381
  return true
366
382
  } catch (err) {
367
- console.error('[Wiki Generation Error]', err);
383
+ console.error(`[Wiki Generation Error] (after ${formatElapsed(buildStart)})`, err);
368
384
  return false
369
385
  }
370
386
  }
@@ -547,6 +563,15 @@ function sqliteStore(config) {
547
563
 
548
564
  const DEFAULT_AUTO_INDEX_HEADER = '# 知識庫目錄';
549
565
 
566
+ function formatElapsed(startMs) {
567
+ const ms = Date.now() - startMs;
568
+ if (ms < 1000) return `${ms}ms`
569
+ if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`
570
+ const m = Math.floor(ms / 60000);
571
+ const s = ((ms % 60000) / 1000).toFixed(1);
572
+ return `${m}m${s}s`
573
+ }
574
+
550
575
  /**
551
576
  * @param {import('./types').TenantManagerConfig} config
552
577
  * @returns {import('./types').TenantManager}
@@ -608,10 +633,14 @@ function createTenantManager(config) {
608
633
  const { force = false } = options;
609
634
  if (buildPromises.has(tenantId)) return buildPromises.get(tenantId)
610
635
 
636
+ const tenantStart = Date.now();
611
637
  const promise = (async () => {
612
638
  const { wiki, store } = getWiki(tenantId);
613
639
  const ok = await wiki.build({ force });
614
- if (!ok) return false
640
+ if (!ok) {
641
+ logger.warn && logger.warn(`[Wiki] Tenant "${tenantId}" build failed — ${formatElapsed(tenantStart)}`);
642
+ return false
643
+ }
615
644
 
616
645
  if (autoIndex) {
617
646
  const hasIndex = await store.read('Index.md');
@@ -622,6 +651,7 @@ function createTenantManager(config) {
622
651
  }
623
652
 
624
653
  builtTenants.add(tenantId);
654
+ logger.log && logger.log(`[Wiki] Tenant "${tenantId}" ready — ${formatElapsed(tenantStart)}`);
625
655
  return true
626
656
  })().finally(() => {
627
657
  buildPromises.delete(tenantId);
@@ -640,8 +670,11 @@ function createTenantManager(config) {
640
670
  logger.log && logger.log('[Wiki] No tenants to build');
641
671
  return []
642
672
  }
673
+ const allStart = Date.now();
643
674
  logger.log && logger.log(`[Wiki] Pre-building ${tenants.length} tenant(s): ${tenants.join(', ')}`);
644
675
  const results = await Promise.allSettled(tenants.map(t => build(t)));
676
+ const okCount = results.filter(r => r.status === 'fulfilled' && r.value === true).length;
677
+ logger.log && logger.log(`[Wiki] buildAll done — ${okCount}/${tenants.length} ok, ${formatElapsed(allStart)}`);
645
678
  results.forEach((r, i) => {
646
679
  if (r.status === 'rejected') {
647
680
  logger.error && logger.error(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jungtz/wiki-router",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "LLM Wiki 知識庫路由引擎 - 將結構化知識轉為 Markdown 維基,智慧路由查詢",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",