ukagaka-doc-mcp 0.1.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.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +24 -0
  3. package/README.md +109 -0
  4. package/SPEC.md +356 -0
  5. package/data/index.json +22046 -0
  6. package/dist/bootstrap.d.ts +17 -0
  7. package/dist/bootstrap.d.ts.map +1 -0
  8. package/dist/bootstrap.js +57 -0
  9. package/dist/bootstrap.js.map +1 -0
  10. package/dist/build-index.d.ts +12 -0
  11. package/dist/build-index.d.ts.map +1 -0
  12. package/dist/build-index.js +51 -0
  13. package/dist/build-index.js.map +1 -0
  14. package/dist/constants.d.ts +77 -0
  15. package/dist/constants.d.ts.map +1 -0
  16. package/dist/constants.js +86 -0
  17. package/dist/constants.js.map +1 -0
  18. package/dist/index-builder.d.ts +5 -0
  19. package/dist/index-builder.d.ts.map +1 -0
  20. package/dist/index-builder.js +53 -0
  21. package/dist/index-builder.js.map +1 -0
  22. package/dist/index-validation.d.ts +9 -0
  23. package/dist/index-validation.d.ts.map +1 -0
  24. package/dist/index-validation.js +75 -0
  25. package/dist/index-validation.js.map +1 -0
  26. package/dist/index.d.ts +11 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +27 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/parser/satori-scraper.d.ts +35 -0
  31. package/dist/parser/satori-scraper.d.ts.map +1 -0
  32. package/dist/parser/satori-scraper.js +272 -0
  33. package/dist/parser/satori-scraper.js.map +1 -0
  34. package/dist/parser/ukadoc-parser.d.ts +21 -0
  35. package/dist/parser/ukadoc-parser.d.ts.map +1 -0
  36. package/dist/parser/ukadoc-parser.js +231 -0
  37. package/dist/parser/ukadoc-parser.js.map +1 -0
  38. package/dist/parser/yaya-scraper.d.ts +46 -0
  39. package/dist/parser/yaya-scraper.d.ts.map +1 -0
  40. package/dist/parser/yaya-scraper.js +308 -0
  41. package/dist/parser/yaya-scraper.js.map +1 -0
  42. package/dist/search/engine.d.ts +41 -0
  43. package/dist/search/engine.d.ts.map +1 -0
  44. package/dist/search/engine.js +114 -0
  45. package/dist/search/engine.js.map +1 -0
  46. package/dist/server.d.ts +12 -0
  47. package/dist/server.d.ts.map +1 -0
  48. package/dist/server.js +36 -0
  49. package/dist/server.js.map +1 -0
  50. package/dist/text.d.ts +2 -0
  51. package/dist/text.d.ts.map +1 -0
  52. package/dist/text.js +8 -0
  53. package/dist/text.js.map +1 -0
  54. package/dist/tools/get-doc.d.ts +4 -0
  55. package/dist/tools/get-doc.d.ts.map +1 -0
  56. package/dist/tools/get-doc.js +29 -0
  57. package/dist/tools/get-doc.js.map +1 -0
  58. package/dist/tools/list-categories.d.ts +3 -0
  59. package/dist/tools/list-categories.d.ts.map +1 -0
  60. package/dist/tools/list-categories.js +21 -0
  61. package/dist/tools/list-categories.js.map +1 -0
  62. package/dist/tools/search-docs.d.ts +4 -0
  63. package/dist/tools/search-docs.d.ts.map +1 -0
  64. package/dist/tools/search-docs.js +45 -0
  65. package/dist/tools/search-docs.js.map +1 -0
  66. package/dist/types.d.ts +59 -0
  67. package/dist/types.d.ts.map +1 -0
  68. package/dist/types.js +5 -0
  69. package/dist/types.js.map +1 -0
  70. package/package.json +64 -0
@@ -0,0 +1,17 @@
1
+ /**
2
+ * bootstrap.ts
3
+ *
4
+ * サーバー起動時の初期化処理:
5
+ * 1. data/index.json を読み込む
6
+ * 2. freshness 判定(7日超なら stderr に警告)
7
+ * 3. SearchEngine にロード
8
+ */
9
+ import { SearchEngine } from './search/engine.js';
10
+ export declare function resolveDefaultIndexPath(): string;
11
+ export declare function getFreshnessWarning(generatedAt: string, now?: number): string | null;
12
+ /**
13
+ * data/index.json を読み込み、SearchEngine を初期化して返す。
14
+ * index.json が存在しない場合は Error を throw する。
15
+ */
16
+ export declare function initializeSearchEngine(indexPath?: string): SearchEngine;
17
+ //# sourceMappingURL=bootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMlD,wBAAgB,uBAAuB,IAAI,MAAM,CAGhD;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,MAAM,GAAG,IAAI,CAYxF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,SAA4B,GAAG,YAAY,CA6B1F"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * bootstrap.ts
3
+ *
4
+ * サーバー起動時の初期化処理:
5
+ * 1. data/index.json を読み込む
6
+ * 2. freshness 判定(7日超なら stderr に警告)
7
+ * 3. SearchEngine にロード
8
+ */
9
+ import { readFileSync, existsSync } from 'node:fs';
10
+ import { resolve } from 'node:path';
11
+ import { fileURLToPath } from 'node:url';
12
+ import { dirname } from 'node:path';
13
+ import { SearchEngine } from './search/engine.js';
14
+ import { STALE_AFTER_DAYS } from './constants.js';
15
+ import { parseAndValidateIndexFile } from './index-validation.js';
16
+ const __dirname = dirname(fileURLToPath(import.meta.url));
17
+ export function resolveDefaultIndexPath() {
18
+ // src/ の親である プロジェクトルートから data/index.json を探す
19
+ return resolve(__dirname, '..', 'data', 'index.json');
20
+ }
21
+ export function getFreshnessWarning(generatedAt, now = Date.now()) {
22
+ const builtAt = new Date(generatedAt);
23
+ if (isNaN(builtAt.getTime())) {
24
+ return null;
25
+ }
26
+ const daysSince = (now - builtAt.getTime()) / (1000 * 60 * 60 * 24);
27
+ if (daysSince > STALE_AFTER_DAYS) {
28
+ const days = Math.floor(daysSince);
29
+ return `[bootstrap] Warning: Index is stale (built ${days} days ago). Consider rebuilding:\n npm run build:index`;
30
+ }
31
+ return null;
32
+ }
33
+ /**
34
+ * data/index.json を読み込み、SearchEngine を初期化して返す。
35
+ * index.json が存在しない場合は Error を throw する。
36
+ */
37
+ export function initializeSearchEngine(indexPath = resolveDefaultIndexPath()) {
38
+ if (!existsSync(indexPath)) {
39
+ throw new Error(`Index file not found: ${indexPath}\n` +
40
+ `Run: npm run build:index`);
41
+ }
42
+ const raw = readFileSync(indexPath, 'utf-8');
43
+ const { indexFile, warnings } = parseAndValidateIndexFile(raw);
44
+ for (const warning of warnings) {
45
+ console.error(warning);
46
+ }
47
+ // freshness 判定
48
+ const freshnessWarning = getFreshnessWarning(indexFile.generatedAt);
49
+ if (freshnessWarning) {
50
+ console.error(freshnessWarning);
51
+ }
52
+ const engine = new SearchEngine();
53
+ engine.load(indexFile.entries);
54
+ console.error(`[bootstrap] Loaded ${engine.size} entries from index (built: ${indexFile.generatedAt})`);
55
+ return engine;
56
+ }
57
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAElE,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,MAAM,UAAU,uBAAuB;IACrC,6CAA6C;IAC7C,OAAO,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,WAAmB,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IACvE,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,SAAS,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IACpE,IAAI,SAAS,GAAG,gBAAgB,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACnC,OAAO,8CAA8C,IAAI,yDAAyD,CAAC;IACrH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAS,GAAG,uBAAuB,EAAE;IAE1E,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,yBAAyB,SAAS,IAAI;YACtC,0BAA0B,CAC3B,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC;IAE/D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAED,eAAe;IACf,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACpE,IAAI,gBAAgB,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;IAClC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/B,OAAO,CAAC,KAAK,CACX,sBAAsB,MAAM,CAAC,IAAI,+BAA+B,SAAS,CAAC,WAAW,GAAG,CACzF,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * ビルドスクリプト
3
+ *
4
+ * npm run build:index で実行する。
5
+ * 全ソース(UKADOC, YAYA Wiki, 里々Wiki)をパース・スクレイプして
6
+ * data/index.json を生成する。
7
+ *
8
+ * Usage:
9
+ * npm run build:index
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=build-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-index.d.ts","sourceRoot":"","sources":["../src/build-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * ビルドスクリプト
3
+ *
4
+ * npm run build:index で実行する。
5
+ * 全ソース(UKADOC, YAYA Wiki, 里々Wiki)をパース・スクレイプして
6
+ * data/index.json を生成する。
7
+ *
8
+ * Usage:
9
+ * npm run build:index
10
+ */
11
+ import { resolve, dirname } from 'node:path';
12
+ import { fileURLToPath } from 'node:url';
13
+ import { parseUkadocManual } from './parser/ukadoc-parser.js';
14
+ import { scrapeYayaWiki } from './parser/yaya-scraper.js';
15
+ import { scrapeSatoriWiki } from './parser/satori-scraper.js';
16
+ import { buildIndexFile, writeIndexAtomically } from './index-builder.js';
17
+ const __dirname = dirname(fileURLToPath(import.meta.url));
18
+ async function main() {
19
+ const startTime = Date.now();
20
+ console.error('[build-index] Starting index build...');
21
+ const entries = [];
22
+ // --- Phase 1: UKADOC ---
23
+ console.error('[build-index] Parsing UKADOC...');
24
+ const ukadocManualDir = resolve(__dirname, '..', 'docs', 'ukadoc', 'manual');
25
+ const ukadocEntries = parseUkadocManual(ukadocManualDir);
26
+ entries.push(...ukadocEntries);
27
+ console.error(`[build-index] UKADOC: ${ukadocEntries.length} entries`);
28
+ // --- Phase 2: YAYA Wiki ---
29
+ console.error('[build-index] Scraping YAYA Wiki...');
30
+ const yayaEntries = await scrapeYayaWiki();
31
+ entries.push(...yayaEntries);
32
+ console.error(`[build-index] YAYA Wiki: ${yayaEntries.length} entries`);
33
+ // --- Phase 3: 里々Wiki ---
34
+ console.error('[build-index] Scraping 里々Wiki...');
35
+ const satoriEntries = await scrapeSatoriWiki();
36
+ entries.push(...satoriEntries);
37
+ console.error(`[build-index] 里々Wiki: ${satoriEntries.length} entries`);
38
+ // --- 統合 ---
39
+ const indexFile = buildIndexFile(entries);
40
+ const outputPath = resolve(__dirname, '..', 'data', 'index.json');
41
+ writeIndexAtomically(outputPath, indexFile);
42
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
43
+ const sizeKb = Math.round(Buffer.byteLength(JSON.stringify(indexFile)) / 1024);
44
+ console.error(`[build-index] Done: ${entries.length} entries, ${sizeKb} KB, ${elapsed}s`);
45
+ console.error(`[build-index] Output: ${outputPath}`);
46
+ }
47
+ main().catch(err => {
48
+ console.error('[build-index] Fatal error:', err);
49
+ process.exit(1);
50
+ });
51
+ //# sourceMappingURL=build-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-index.js","sourceRoot":"","sources":["../src/build-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1E,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAEvD,MAAM,OAAO,GAAe,EAAE,CAAC;IAE/B,0BAA0B;IAC1B,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACjD,MAAM,eAAe,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC7E,MAAM,aAAa,GAAG,iBAAiB,CAAC,eAAe,CAAC,CAAC;IACzD,OAAO,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC;IAC/B,OAAO,CAAC,KAAK,CAAC,yBAAyB,aAAa,CAAC,MAAM,UAAU,CAAC,CAAC;IAEvE,6BAA6B;IAC7B,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACrD,MAAM,WAAW,GAAG,MAAM,cAAc,EAAE,CAAC;IAC3C,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;IAC7B,OAAO,CAAC,KAAK,CAAC,4BAA4B,WAAW,CAAC,MAAM,UAAU,CAAC,CAAC;IAExE,0BAA0B;IAC1B,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAClD,MAAM,aAAa,GAAG,MAAM,gBAAgB,EAAE,CAAC;IAC/C,OAAO,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC;IAC/B,OAAO,CAAC,KAAK,CAAC,yBAAyB,aAAa,CAAC,MAAM,UAAU,CAAC,CAAC;IAEvE,aAAa;IACb,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;IAClE,oBAAoB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAE5C,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAE/E,OAAO,CAAC,KAAK,CAAC,uBAAuB,OAAO,CAAC,MAAM,aAAa,MAAM,QAAQ,OAAO,GAAG,CAAC,CAAC;IAC1F,OAAO,CAAC,KAAK,CAAC,yBAAyB,UAAU,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;IACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,77 @@
1
+ import type { Source } from './types.js';
2
+ /** インデックスが stale とみなされるまでの日数 */
3
+ export declare const STALE_AFTER_DAYS = 7;
4
+ /** インデックスファイルの現在のスキーマバージョン */
5
+ export declare const INDEX_SCHEMA_VERSION = 1;
6
+ /** search_docs で返す summary の最大文字数 */
7
+ export declare const SUMMARY_MAX_LENGTH = 500;
8
+ /** ビルド時スクレイプのレート制限 (ms) */
9
+ export declare const SCRAPE_RATE_LIMIT_MS = 500;
10
+ export declare const CATEGORIES: {
11
+ readonly sakurascript: {
12
+ readonly source: Source;
13
+ readonly label: "さくらスクリプト命令";
14
+ };
15
+ readonly shiori_event: {
16
+ readonly source: Source;
17
+ readonly label: "SHIORIイベント一覧";
18
+ };
19
+ readonly descript: {
20
+ readonly source: Source;
21
+ readonly label: "設定ファイル仕様(descript.txt / surfaces.txt 等)";
22
+ };
23
+ readonly protocol: {
24
+ readonly source: Source;
25
+ readonly label: "プロトコル仕様(SHIORI/3.0, SSTP 等)";
26
+ };
27
+ readonly file_structure: {
28
+ readonly source: Source;
29
+ readonly label: "ファイル構成・ディレクトリ構造";
30
+ };
31
+ readonly dev_guide: {
32
+ readonly source: Source;
33
+ readonly label: "開発ガイド(シェル作成, NAR作成 等)";
34
+ };
35
+ readonly yaya_grammar: {
36
+ readonly source: Source;
37
+ readonly label: "YAYA言語文法";
38
+ };
39
+ readonly yaya_basic: {
40
+ readonly source: Source;
41
+ readonly label: "YAYA基礎概念(変数・関数・制御構造)";
42
+ };
43
+ readonly yaya_function: {
44
+ readonly source: Source;
45
+ readonly label: "YAYA組み込み関数";
46
+ };
47
+ readonly yaya_system: {
48
+ readonly source: Source;
49
+ readonly label: "YAYAシステム辞書";
50
+ };
51
+ readonly yaya_tips: {
52
+ readonly source: Source;
53
+ readonly label: "実践Tips(YAYA)";
54
+ };
55
+ readonly yaya_startup: {
56
+ readonly source: Source;
57
+ readonly label: "チュートリアル・移行ガイド(YAYA)";
58
+ };
59
+ readonly satori_reference: {
60
+ readonly source: Source;
61
+ readonly label: "里々リファレンス(特殊記号・演算子・変数・関数)";
62
+ };
63
+ readonly satori_event: {
64
+ readonly source: Source;
65
+ readonly label: "里々独自イベント";
66
+ };
67
+ readonly satori_tips: {
68
+ readonly source: Source;
69
+ readonly label: "実践Tips(里々)";
70
+ };
71
+ readonly satori_saori: {
72
+ readonly source: Source;
73
+ readonly label: "里々 SAORI連携";
74
+ };
75
+ };
76
+ export type CategoryKey = keyof typeof CATEGORIES;
77
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,gCAAgC;AAChC,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,8BAA8B;AAC9B,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,qCAAqC;AACrC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,2BAA2B;AAC3B,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAQxC,eAAO,MAAM,UAAU;;yBAGC,MAAM;;;;yBAIN,MAAM;;;;yBAIN,MAAM;;;;yBAIN,MAAM;;;;yBAIN,MAAM;;;;yBAIN,MAAM;;;;yBAMH,MAAM;;;;yBAIN,MAAM;;;;yBAIN,MAAM;;;;yBAIN,MAAM;;;;yBAIN,MAAM;;;;yBAIN,MAAM;;;;yBAMJ,MAAM;;;;yBAIN,MAAM;;;;yBAIN,MAAM;;;;yBAIN,MAAM;;;CAGzB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,UAAU,CAAC"}
@@ -0,0 +1,86 @@
1
+ // ============================================================
2
+ // 定数定義(単一ソース)
3
+ // ============================================================
4
+ /** インデックスが stale とみなされるまでの日数 */
5
+ export const STALE_AFTER_DAYS = 7;
6
+ /** インデックスファイルの現在のスキーマバージョン */
7
+ export const INDEX_SCHEMA_VERSION = 1;
8
+ /** search_docs で返す summary の最大文字数 */
9
+ export const SUMMARY_MAX_LENGTH = 500;
10
+ /** ビルド時スクレイプのレート制限 (ms) */
11
+ export const SCRAPE_RATE_LIMIT_MS = 500;
12
+ // ============================================================
13
+ // カテゴリ定義
14
+ // ソースとカテゴリIDの対応を一元管理。
15
+ // パーサー・ツール・テスト全てがここから参照する。
16
+ // ============================================================
17
+ export const CATEGORIES = {
18
+ // --- UKADOC ---
19
+ sakurascript: {
20
+ source: 'ukadoc',
21
+ label: 'さくらスクリプト命令',
22
+ },
23
+ shiori_event: {
24
+ source: 'ukadoc',
25
+ label: 'SHIORIイベント一覧',
26
+ },
27
+ descript: {
28
+ source: 'ukadoc',
29
+ label: '設定ファイル仕様(descript.txt / surfaces.txt 等)',
30
+ },
31
+ protocol: {
32
+ source: 'ukadoc',
33
+ label: 'プロトコル仕様(SHIORI/3.0, SSTP 等)',
34
+ },
35
+ file_structure: {
36
+ source: 'ukadoc',
37
+ label: 'ファイル構成・ディレクトリ構造',
38
+ },
39
+ dev_guide: {
40
+ source: 'ukadoc',
41
+ label: '開発ガイド(シェル作成, NAR作成 等)',
42
+ },
43
+ // --- YAYA Wiki ---
44
+ yaya_grammar: {
45
+ source: 'yaya_wiki',
46
+ label: 'YAYA言語文法',
47
+ },
48
+ yaya_basic: {
49
+ source: 'yaya_wiki',
50
+ label: 'YAYA基礎概念(変数・関数・制御構造)',
51
+ },
52
+ yaya_function: {
53
+ source: 'yaya_wiki',
54
+ label: 'YAYA組み込み関数',
55
+ },
56
+ yaya_system: {
57
+ source: 'yaya_wiki',
58
+ label: 'YAYAシステム辞書',
59
+ },
60
+ yaya_tips: {
61
+ source: 'yaya_wiki',
62
+ label: '実践Tips(YAYA)',
63
+ },
64
+ yaya_startup: {
65
+ source: 'yaya_wiki',
66
+ label: 'チュートリアル・移行ガイド(YAYA)',
67
+ },
68
+ // --- 里々Wiki ---
69
+ satori_reference: {
70
+ source: 'satori_wiki',
71
+ label: '里々リファレンス(特殊記号・演算子・変数・関数)',
72
+ },
73
+ satori_event: {
74
+ source: 'satori_wiki',
75
+ label: '里々独自イベント',
76
+ },
77
+ satori_tips: {
78
+ source: 'satori_wiki',
79
+ label: '実践Tips(里々)',
80
+ },
81
+ satori_saori: {
82
+ source: 'satori_wiki',
83
+ label: '里々 SAORI連携',
84
+ },
85
+ };
86
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,cAAc;AACd,+DAA+D;AAI/D,gCAAgC;AAChC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAElC,8BAA8B;AAC9B,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAEtC,qCAAqC;AACrC,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAEtC,2BAA2B;AAC3B,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAExC,+DAA+D;AAC/D,SAAS;AACT,sBAAsB;AACtB,2BAA2B;AAC3B,+DAA+D;AAE/D,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,iBAAiB;IACjB,YAAY,EAAE;QACZ,MAAM,EAAE,QAAkB;QAC1B,KAAK,EAAE,YAAY;KACpB;IACD,YAAY,EAAE;QACZ,MAAM,EAAE,QAAkB;QAC1B,KAAK,EAAE,cAAc;KACtB;IACD,QAAQ,EAAE;QACR,MAAM,EAAE,QAAkB;QAC1B,KAAK,EAAE,yCAAyC;KACjD;IACD,QAAQ,EAAE;QACR,MAAM,EAAE,QAAkB;QAC1B,KAAK,EAAE,6BAA6B;KACrC;IACD,cAAc,EAAE;QACd,MAAM,EAAE,QAAkB;QAC1B,KAAK,EAAE,iBAAiB;KACzB;IACD,SAAS,EAAE;QACT,MAAM,EAAE,QAAkB;QAC1B,KAAK,EAAE,uBAAuB;KAC/B;IAED,oBAAoB;IACpB,YAAY,EAAE;QACZ,MAAM,EAAE,WAAqB;QAC7B,KAAK,EAAE,UAAU;KAClB;IACD,UAAU,EAAE;QACV,MAAM,EAAE,WAAqB;QAC7B,KAAK,EAAE,sBAAsB;KAC9B;IACD,aAAa,EAAE;QACb,MAAM,EAAE,WAAqB;QAC7B,KAAK,EAAE,YAAY;KACpB;IACD,WAAW,EAAE;QACX,MAAM,EAAE,WAAqB;QAC7B,KAAK,EAAE,YAAY;KACpB;IACD,SAAS,EAAE;QACT,MAAM,EAAE,WAAqB;QAC7B,KAAK,EAAE,cAAc;KACtB;IACD,YAAY,EAAE;QACZ,MAAM,EAAE,WAAqB;QAC7B,KAAK,EAAE,qBAAqB;KAC7B;IAED,iBAAiB;IACjB,gBAAgB,EAAE;QAChB,MAAM,EAAE,aAAuB;QAC/B,KAAK,EAAE,0BAA0B;KAClC;IACD,YAAY,EAAE;QACZ,MAAM,EAAE,aAAuB;QAC/B,KAAK,EAAE,UAAU;KAClB;IACD,WAAW,EAAE;QACX,MAAM,EAAE,aAAuB;QAC/B,KAAK,EAAE,YAAY;KACpB;IACD,YAAY,EAAE;QACZ,MAAM,EAAE,aAAuB;QAC/B,KAAK,EAAE,YAAY;KACpB;CACO,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { DocEntry, IndexFile } from './types.js';
2
+ export declare function buildIndexFile(entries: DocEntry[], generatedAt?: string): IndexFile;
3
+ export declare function validateEntriesForBuild(entries: DocEntry[]): void;
4
+ export declare function writeIndexAtomically(outputPath: string, indexFile: IndexFile): void;
5
+ //# sourceMappingURL=index-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-builder.d.ts","sourceRoot":"","sources":["../src/index-builder.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAU,MAAM,YAAY,CAAC;AAK9D,wBAAgB,cAAc,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,WAAW,SAA2B,GAAG,SAAS,CAQrG;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,CAyBjE;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,CAgBnF"}
@@ -0,0 +1,53 @@
1
+ import { existsSync, mkdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { basename, dirname, join } from 'node:path';
3
+ import { INDEX_SCHEMA_VERSION } from './constants.js';
4
+ import { findDuplicateIds } from './index-validation.js';
5
+ const REQUIRED_SOURCES = ['ukadoc', 'yaya_wiki', 'satori_wiki'];
6
+ const INVALID_PAGE_MARKERS = ['有効なWikiNameではありません'];
7
+ export function buildIndexFile(entries, generatedAt = new Date().toISOString()) {
8
+ validateEntriesForBuild(entries);
9
+ return {
10
+ version: INDEX_SCHEMA_VERSION,
11
+ generatedAt,
12
+ entries,
13
+ };
14
+ }
15
+ export function validateEntriesForBuild(entries) {
16
+ if (entries.length === 0) {
17
+ throw new Error('No entries collected');
18
+ }
19
+ const duplicateIds = findDuplicateIds(entries);
20
+ if (duplicateIds.length > 0) {
21
+ throw new Error(`Duplicate ids found: ${duplicateIds.slice(0, 10).join(', ')}`);
22
+ }
23
+ const invalidEntries = entries.filter(isInvalidEntry);
24
+ if (invalidEntries.length > 0) {
25
+ throw new Error(`Invalid pages detected in index entries: ${invalidEntries.slice(0, 10).map(entry => entry.id).join(', ')}`);
26
+ }
27
+ const sources = new Map();
28
+ for (const entry of entries) {
29
+ sources.set(entry.source, (sources.get(entry.source) ?? 0) + 1);
30
+ }
31
+ for (const source of REQUIRED_SOURCES) {
32
+ if (!sources.has(source)) {
33
+ throw new Error(`Missing entries for required source: ${source}`);
34
+ }
35
+ }
36
+ }
37
+ export function writeIndexAtomically(outputPath, indexFile) {
38
+ mkdirSync(dirname(outputPath), { recursive: true });
39
+ const tempPath = join(dirname(outputPath), `.${basename(outputPath)}.${process.pid}.${Date.now()}.tmp`);
40
+ try {
41
+ writeFileSync(tempPath, JSON.stringify(indexFile, null, 2), 'utf-8');
42
+ renameSync(tempPath, outputPath);
43
+ }
44
+ finally {
45
+ if (existsSync(tempPath)) {
46
+ rmSync(tempPath, { force: true });
47
+ }
48
+ }
49
+ }
50
+ function isInvalidEntry(entry) {
51
+ return INVALID_PAGE_MARKERS.some(marker => entry.title.includes(marker) || entry.content.includes(marker));
52
+ }
53
+ //# sourceMappingURL=index-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-builder.js","sourceRoot":"","sources":["../src/index-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { DocEntry, IndexFile } from './types.js';
2
+ export interface IndexValidationResult {
3
+ indexFile: IndexFile;
4
+ warnings: string[];
5
+ }
6
+ export declare function parseAndValidateIndexFile(raw: string): IndexValidationResult;
7
+ export declare function validateIndexFile(value: unknown): IndexValidationResult;
8
+ export declare function findDuplicateIds(entries: Array<Pick<DocEntry, 'id'>>): string[];
9
+ //# sourceMappingURL=index-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-validation.d.ts","sourceRoot":"","sources":["../src/index-validation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAY,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAoBhE,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,CAU5E;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,qBAAqB,CAiDvE;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,GAAG,MAAM,EAAE,CAU/E"}
@@ -0,0 +1,75 @@
1
+ import { z } from 'zod';
2
+ import { CATEGORIES, INDEX_SCHEMA_VERSION } from './constants.js';
3
+ const SOURCE_VALUES = ['ukadoc', 'yaya_wiki', 'satori_wiki'];
4
+ const KNOWN_CATEGORY_SET = new Set(Object.keys(CATEGORIES));
5
+ const rawDocEntrySchema = z.object({
6
+ id: z.string().min(1),
7
+ title: z.string().min(1),
8
+ source: z.enum(SOURCE_VALUES),
9
+ category: z.string().min(1),
10
+ content: z.string().min(1),
11
+ url: z.string().min(1),
12
+ });
13
+ const rawIndexFileSchema = z.object({
14
+ version: z.number(),
15
+ generatedAt: z.string(),
16
+ entries: z.array(rawDocEntrySchema).nonempty(),
17
+ });
18
+ export function parseAndValidateIndexFile(raw) {
19
+ let parsed;
20
+ try {
21
+ parsed = JSON.parse(raw);
22
+ }
23
+ catch (error) {
24
+ throw new Error(`Failed to parse index.json: ${error}`);
25
+ }
26
+ return validateIndexFile(parsed);
27
+ }
28
+ export function validateIndexFile(value) {
29
+ const parsed = rawIndexFileSchema.safeParse(value);
30
+ if (!parsed.success) {
31
+ throw new Error(`Invalid index.json structure: ${parsed.error.issues.map(issue => issue.path.join('.') || '(root)').join(', ')}`);
32
+ }
33
+ const warnings = [];
34
+ if (parsed.data.version !== INDEX_SCHEMA_VERSION) {
35
+ warnings.push(`[bootstrap] Warning: Index schema version mismatch (expected ${INDEX_SCHEMA_VERSION}, got ${parsed.data.version}). Consider rebuilding: npm run build:index`);
36
+ }
37
+ if (Number.isNaN(new Date(parsed.data.generatedAt).getTime())) {
38
+ warnings.push('[bootstrap] Warning: Invalid generatedAt in index.json');
39
+ }
40
+ const unknownCategoryEntries = parsed.data.entries.filter(entry => !KNOWN_CATEGORY_SET.has(entry.category));
41
+ if (unknownCategoryEntries.length > 0) {
42
+ warnings.push(`[bootstrap] Warning: Dropping ${unknownCategoryEntries.length} entries with unknown categories.`);
43
+ }
44
+ const entries = parsed.data.entries
45
+ .filter((entry) => KNOWN_CATEGORY_SET.has(entry.category))
46
+ .map(entry => ({
47
+ ...entry,
48
+ category: entry.category,
49
+ }));
50
+ if (entries.length === 0) {
51
+ throw new Error('Index has no valid entries');
52
+ }
53
+ const duplicateIds = findDuplicateIds(entries);
54
+ if (duplicateIds.length > 0) {
55
+ throw new Error(`Index contains duplicate ids: ${duplicateIds.slice(0, 10).join(', ')}`);
56
+ }
57
+ return {
58
+ indexFile: {
59
+ version: parsed.data.version,
60
+ generatedAt: parsed.data.generatedAt,
61
+ entries,
62
+ },
63
+ warnings,
64
+ };
65
+ }
66
+ export function findDuplicateIds(entries) {
67
+ const counts = new Map();
68
+ for (const entry of entries) {
69
+ counts.set(entry.id, (counts.get(entry.id) ?? 0) + 1);
70
+ }
71
+ return [...counts.entries()]
72
+ .filter(([, count]) => count > 1)
73
+ .map(([id]) => id);
74
+ }
75
+ //# sourceMappingURL=index-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-validation.js","sourceRoot":"","sources":["../src/index-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAGlE,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,aAAa,CAAU,CAAC;AACtE,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;AAE5D,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC;IAC7B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,QAAQ,EAAE;CAC/C,CAAC,CAAC;AAOH,MAAM,UAAU,yBAAyB,CAAC,GAAW;IACnD,IAAI,MAAe,CAAC;IAEpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,+BAA+B,KAAK,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,iCAAiC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpI,CAAC;IAED,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,oBAAoB,EAAE,CAAC;QACjD,QAAQ,CAAC,IAAI,CACX,gEAAgE,oBAAoB,SAAS,MAAM,CAAC,IAAI,CAAC,OAAO,6CAA6C,CAC9J,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QAC9D,QAAQ,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,sBAAsB,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC5G,IAAI,sBAAsB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,QAAQ,CAAC,IAAI,CACX,iCAAiC,sBAAsB,CAAC,MAAM,mCAAmC,CAClG,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO;SAChC,MAAM,CAAC,CAAC,KAAK,EAAkD,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;SACzG,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACb,GAAG,KAAK;QACR,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC,CAAC,CAAC;IAEN,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,YAAY,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,iCAAiC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3F,CAAC;IAED,OAAO;QACL,SAAS,EAAE;YACT,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO;YAC5B,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW;YACpC,OAAO;SACR;QACD,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAoC;IACnE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEzC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SACzB,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;AACvB,CAAC"}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * エントリポイント
4
+ *
5
+ * 起動シーケンス:
6
+ * 1. data/index.json をロード + freshness 判定
7
+ * 2. MCPサーバー作成
8
+ * 3. stdio トランスポートで接続
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG"}
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * エントリポイント
4
+ *
5
+ * 起動シーケンス:
6
+ * 1. data/index.json をロード + freshness 判定
7
+ * 2. MCPサーバー作成
8
+ * 3. stdio トランスポートで接続
9
+ */
10
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
11
+ import { initializeSearchEngine } from './bootstrap.js';
12
+ import { createMcpServer } from './server.js';
13
+ async function main() {
14
+ // 1. index ロード(失敗時は Error をthrowしてプロセス終了)
15
+ const engine = initializeSearchEngine();
16
+ // 2. MCPサーバー作成
17
+ const server = createMcpServer(engine);
18
+ // 3. stdio 接続
19
+ const transport = new StdioServerTransport();
20
+ await server.connect(transport);
21
+ console.error('[ukagaka-doc-mcp] Server ready');
22
+ }
23
+ main().catch(err => {
24
+ console.error('[ukagaka-doc-mcp] Fatal:', err instanceof Error ? err.message : err);
25
+ process.exit(1);
26
+ });
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,KAAK,UAAU,IAAI;IACjB,0CAA0C;IAC1C,MAAM,MAAM,GAAG,sBAAsB,EAAE,CAAC;IAExC,eAAe;IACf,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAEvC,cAAc;IACd,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;AAClD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * 里々Wiki スクレイパー
3
+ *
4
+ * https://soliton.sub.jp/satori/ (PukiWiki 1.5.4)
5
+ *
6
+ * 里々Wikiのコンテンツ構造:
7
+ * - 資料系: 特殊記号一覧, 演算子一覧, 変数, 情報取得変数, 特殊変数, 関数一覧, ファイル構成
8
+ * - 独自イベント
9
+ * - TIPS: TIPS総合, ゴースト作りのTIPSまとめ, 困ったときの対処法 + 個別TIPSページ
10
+ * - 里々について: 里々の内部処理, 栞としての里々
11
+ * - SAORI: SAORI, SAORI/里々
12
+ */
13
+ import type { DocEntry, Category } from '../types.js';
14
+ interface SatoriPageDef {
15
+ /** Wiki ページ名 (?ページ名 の形式) */
16
+ pageName: string;
17
+ category: Category;
18
+ }
19
+ /** 静的スクレイプ対象ページ */
20
+ export declare const SATORI_STATIC_PAGES: SatoriPageDef[];
21
+ /**
22
+ * 里々WikiページのHTMLをパースして DocEntry[] を返す。
23
+ */
24
+ export declare function parseSatoriPage(html: string, pageName: string, category: Category): DocEntry[];
25
+ /**
26
+ * TIPS総合ページからリンクされている個別Tipsページを収集する。
27
+ */
28
+ export declare function fetchSatoriTipsPageList(): Promise<string[]>;
29
+ /**
30
+ * 里々Wiki全体をスクレイプして DocEntry[] を返す。
31
+ */
32
+ export declare function scrapeSatoriWiki(): Promise<DocEntry[]>;
33
+ export declare function normalizeSatoriWikiHref(href: string | undefined): string | null;
34
+ export {};
35
+ //# sourceMappingURL=satori-scraper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"satori-scraper.d.ts","sourceRoot":"","sources":["../../src/parser/satori-scraper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAUtD,UAAU,aAAa;IACrB,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,mBAAmB;AACnB,eAAO,MAAM,mBAAmB,EAAE,aAAa,EAsB9C,CAAC;AAmCF;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,GACjB,QAAQ,EAAE,CA+FZ;AAMD;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAgCjE;AAMD;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAkC5D;AAwBD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAoB/E"}