@nahisaho/shikigami-mcp-server 1.7.0 → 1.10.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 (114) hide show
  1. package/README.md +29 -0
  2. package/dist/cache/__tests__/global.test.d.ts +6 -0
  3. package/dist/cache/__tests__/global.test.d.ts.map +1 -0
  4. package/dist/cache/__tests__/global.test.js +269 -0
  5. package/dist/cache/__tests__/global.test.js.map +1 -0
  6. package/dist/cache/__tests__/manager.test.d.ts +6 -0
  7. package/dist/cache/__tests__/manager.test.d.ts.map +1 -0
  8. package/dist/cache/__tests__/manager.test.js +286 -0
  9. package/dist/cache/__tests__/manager.test.js.map +1 -0
  10. package/dist/cache/__tests__/semantic.test.d.ts +6 -0
  11. package/dist/cache/__tests__/semantic.test.d.ts.map +1 -0
  12. package/dist/cache/__tests__/semantic.test.js +271 -0
  13. package/dist/cache/__tests__/semantic.test.js.map +1 -0
  14. package/dist/cache/__tests__/store.test.d.ts +6 -0
  15. package/dist/cache/__tests__/store.test.d.ts.map +1 -0
  16. package/dist/cache/__tests__/store.test.js +289 -0
  17. package/dist/cache/__tests__/store.test.js.map +1 -0
  18. package/dist/cache/global.d.ts +140 -0
  19. package/dist/cache/global.d.ts.map +1 -0
  20. package/dist/cache/global.js +260 -0
  21. package/dist/cache/global.js.map +1 -0
  22. package/dist/cache/index.d.ts +10 -0
  23. package/dist/cache/index.d.ts.map +1 -0
  24. package/dist/cache/index.js +10 -0
  25. package/dist/cache/index.js.map +1 -0
  26. package/dist/cache/manager.d.ts +146 -0
  27. package/dist/cache/manager.d.ts.map +1 -0
  28. package/dist/cache/manager.js +229 -0
  29. package/dist/cache/manager.js.map +1 -0
  30. package/dist/cache/semantic.d.ts +164 -0
  31. package/dist/cache/semantic.d.ts.map +1 -0
  32. package/dist/cache/semantic.js +241 -0
  33. package/dist/cache/semantic.js.map +1 -0
  34. package/dist/cache/store.d.ts +98 -0
  35. package/dist/cache/store.d.ts.map +1 -0
  36. package/dist/cache/store.js +469 -0
  37. package/dist/cache/store.js.map +1 -0
  38. package/dist/cache/types.d.ts +171 -0
  39. package/dist/cache/types.d.ts.map +1 -0
  40. package/dist/cache/types.js +8 -0
  41. package/dist/cache/types.js.map +1 -0
  42. package/dist/config/types.d.ts +67 -0
  43. package/dist/config/types.d.ts.map +1 -1
  44. package/dist/config/types.js +30 -0
  45. package/dist/config/types.js.map +1 -1
  46. package/dist/tools/__tests__/multilingual-search.test.d.ts +7 -0
  47. package/dist/tools/__tests__/multilingual-search.test.d.ts.map +1 -0
  48. package/dist/tools/__tests__/multilingual-search.test.js +71 -0
  49. package/dist/tools/__tests__/multilingual-search.test.js.map +1 -0
  50. package/dist/tools/search/recovery/__tests__/logger.test.d.ts +8 -0
  51. package/dist/tools/search/recovery/__tests__/logger.test.d.ts.map +1 -0
  52. package/dist/tools/search/recovery/__tests__/logger.test.js +249 -0
  53. package/dist/tools/search/recovery/__tests__/logger.test.js.map +1 -0
  54. package/dist/tools/search/recovery/__tests__/manager-logger.test.d.ts +8 -0
  55. package/dist/tools/search/recovery/__tests__/manager-logger.test.d.ts.map +1 -0
  56. package/dist/tools/search/recovery/__tests__/manager-logger.test.js +158 -0
  57. package/dist/tools/search/recovery/__tests__/manager-logger.test.js.map +1 -0
  58. package/dist/tools/search/recovery/index.d.ts +31 -2
  59. package/dist/tools/search/recovery/index.d.ts.map +1 -1
  60. package/dist/tools/search/recovery/index.js +51 -7
  61. package/dist/tools/search/recovery/index.js.map +1 -1
  62. package/dist/tools/search/recovery/logger.d.ts +149 -0
  63. package/dist/tools/search/recovery/logger.d.ts.map +1 -0
  64. package/dist/tools/search/recovery/logger.js +218 -0
  65. package/dist/tools/search/recovery/logger.js.map +1 -0
  66. package/dist/tools/search.d.ts +48 -0
  67. package/dist/tools/search.d.ts.map +1 -1
  68. package/dist/tools/search.js +152 -0
  69. package/dist/tools/search.js.map +1 -1
  70. package/dist/tools/visit/recovery/__tests__/index.test.d.ts +10 -0
  71. package/dist/tools/visit/recovery/__tests__/index.test.d.ts.map +1 -0
  72. package/dist/tools/visit/recovery/__tests__/index.test.js +239 -0
  73. package/dist/tools/visit/recovery/__tests__/index.test.js.map +1 -0
  74. package/dist/tools/visit/recovery/__tests__/wayback.test.d.ts +8 -0
  75. package/dist/tools/visit/recovery/__tests__/wayback.test.d.ts.map +1 -0
  76. package/dist/tools/visit/recovery/__tests__/wayback.test.js +271 -0
  77. package/dist/tools/visit/recovery/__tests__/wayback.test.js.map +1 -0
  78. package/dist/tools/visit/recovery/index.d.ts +126 -0
  79. package/dist/tools/visit/recovery/index.d.ts.map +1 -0
  80. package/dist/tools/visit/recovery/index.js +203 -0
  81. package/dist/tools/visit/recovery/index.js.map +1 -0
  82. package/dist/tools/visit/recovery/wayback.d.ts +101 -0
  83. package/dist/tools/visit/recovery/wayback.d.ts.map +1 -0
  84. package/dist/tools/visit/recovery/wayback.js +140 -0
  85. package/dist/tools/visit/recovery/wayback.js.map +1 -0
  86. package/dist/tools/visit.d.ts +33 -0
  87. package/dist/tools/visit.d.ts.map +1 -1
  88. package/dist/tools/visit.js +127 -1
  89. package/dist/tools/visit.js.map +1 -1
  90. package/package.json +7 -3
  91. package/shikigami.config.example.yaml +9 -0
  92. package/src/cache/__tests__/global.test.ts +340 -0
  93. package/src/cache/__tests__/manager.test.ts +353 -0
  94. package/src/cache/__tests__/semantic.test.ts +331 -0
  95. package/src/cache/__tests__/store.test.ts +369 -0
  96. package/src/cache/global.ts +351 -0
  97. package/src/cache/index.ts +10 -0
  98. package/src/cache/manager.ts +325 -0
  99. package/src/cache/semantic.ts +368 -0
  100. package/src/cache/store.ts +555 -0
  101. package/src/cache/types.ts +189 -0
  102. package/src/config/types.ts +108 -0
  103. package/src/tools/__tests__/multilingual-search.test.ts +88 -0
  104. package/src/tools/search/recovery/__tests__/logger.test.ts +334 -0
  105. package/src/tools/search/recovery/__tests__/manager-logger.test.ts +199 -0
  106. package/src/tools/search/recovery/index.ts +67 -9
  107. package/src/tools/search/recovery/logger.ts +351 -0
  108. package/src/tools/search.ts +212 -0
  109. package/src/tools/visit/recovery/__tests__/index.test.ts +297 -0
  110. package/src/tools/visit/recovery/__tests__/wayback.test.ts +344 -0
  111. package/src/tools/visit/recovery/index.ts +312 -0
  112. package/src/tools/visit/recovery/wayback.ts +210 -0
  113. package/src/tools/visit.ts +159 -2
  114. package/vitest.config.ts +22 -0
@@ -0,0 +1,271 @@
1
+ /**
2
+ * WaybackClient テスト
3
+ *
4
+ * TSK-1-003: WaybackClient実装
5
+ * REQ-SRCH-004-01: visit失敗時フォールバック
6
+ */
7
+ import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
8
+ import { WaybackClient, createWaybackClient, } from '../wayback.js';
9
+ // globalThis.fetch をモック
10
+ const mockFetch = vi.fn();
11
+ vi.stubGlobal('fetch', mockFetch);
12
+ describe('WaybackClient', () => {
13
+ let client;
14
+ beforeEach(() => {
15
+ client = new WaybackClient();
16
+ mockFetch.mockReset();
17
+ vi.spyOn(console, 'error').mockImplementation(() => { });
18
+ });
19
+ afterEach(() => {
20
+ vi.restoreAllMocks();
21
+ });
22
+ describe('constructor', () => {
23
+ it('should use default config when no config provided', () => {
24
+ const client = new WaybackClient();
25
+ expect(client).toBeInstanceOf(WaybackClient);
26
+ });
27
+ it('should merge custom config with defaults', () => {
28
+ const client = new WaybackClient({ timeoutMs: 5000 });
29
+ expect(client).toBeInstanceOf(WaybackClient);
30
+ });
31
+ });
32
+ describe('getSnapshot', () => {
33
+ it('should return snapshot when archive is available', async () => {
34
+ const mockResponse = {
35
+ url: 'https://example.com',
36
+ archived_snapshots: {
37
+ closest: {
38
+ url: 'https://web.archive.org/web/20240101120000/https://example.com',
39
+ timestamp: '20240101120000',
40
+ available: true,
41
+ status: '200',
42
+ },
43
+ },
44
+ };
45
+ mockFetch.mockResolvedValueOnce({
46
+ ok: true,
47
+ json: async () => mockResponse,
48
+ });
49
+ const result = await client.getSnapshot('https://example.com');
50
+ expect(result).not.toBeNull();
51
+ expect(result?.url).toBe('https://web.archive.org/web/20240101120000/https://example.com');
52
+ expect(result?.originalUrl).toBe('https://example.com');
53
+ expect(result?.available).toBe(true);
54
+ expect(result?.timestamp).toBe('2024-01-01T12:00:00Z');
55
+ expect(result?.status).toBe(200);
56
+ });
57
+ it('should return null when no archive is available', async () => {
58
+ const mockResponse = {
59
+ url: 'https://example.com',
60
+ archived_snapshots: {},
61
+ };
62
+ mockFetch.mockResolvedValueOnce({
63
+ ok: true,
64
+ json: async () => mockResponse,
65
+ });
66
+ const result = await client.getSnapshot('https://example.com');
67
+ expect(result).toBeNull();
68
+ });
69
+ it('should retry on failure', async () => {
70
+ const mockResponse = {
71
+ url: 'https://example.com',
72
+ archived_snapshots: {
73
+ closest: {
74
+ url: 'https://web.archive.org/web/20240101120000/https://example.com',
75
+ timestamp: '20240101120000',
76
+ available: true,
77
+ },
78
+ },
79
+ };
80
+ // 最初の2回は失敗、3回目で成功
81
+ mockFetch
82
+ .mockRejectedValueOnce(new Error('Network error'))
83
+ .mockRejectedValueOnce(new Error('Network error'))
84
+ .mockResolvedValueOnce({
85
+ ok: true,
86
+ json: async () => mockResponse,
87
+ });
88
+ // リトライ間隔を短くして高速化
89
+ const fastClient = new WaybackClient({ retryDelayMs: 10 });
90
+ const result = await fastClient.getSnapshot('https://example.com');
91
+ expect(result).not.toBeNull();
92
+ expect(mockFetch).toHaveBeenCalledTimes(3);
93
+ });
94
+ it('should return null after all retries fail', async () => {
95
+ mockFetch.mockRejectedValue(new Error('Network error'));
96
+ const fastClient = new WaybackClient({ retryDelayMs: 10, maxRetries: 2 });
97
+ const result = await fastClient.getSnapshot('https://example.com');
98
+ expect(result).toBeNull();
99
+ expect(mockFetch).toHaveBeenCalledTimes(3); // 初回 + 2回リトライ
100
+ });
101
+ it('should handle HTTP errors', async () => {
102
+ mockFetch.mockResolvedValue({
103
+ ok: false,
104
+ status: 503,
105
+ statusText: 'Service Unavailable',
106
+ });
107
+ const fastClient = new WaybackClient({ retryDelayMs: 10, maxRetries: 0 });
108
+ const result = await fastClient.getSnapshot('https://example.com');
109
+ expect(result).toBeNull();
110
+ });
111
+ it('should handle timeout', async () => {
112
+ // タイムアウトをシミュレート
113
+ mockFetch.mockImplementation(() => new Promise((_, reject) => {
114
+ const error = new Error('Aborted');
115
+ error.name = 'AbortError';
116
+ reject(error);
117
+ }));
118
+ const fastClient = new WaybackClient({ timeoutMs: 100, maxRetries: 0 });
119
+ const result = await fastClient.getSnapshot('https://example.com');
120
+ expect(result).toBeNull();
121
+ });
122
+ });
123
+ describe('isArchived', () => {
124
+ it('should return true when archive is available', async () => {
125
+ const mockResponse = {
126
+ url: 'https://example.com',
127
+ archived_snapshots: {
128
+ closest: {
129
+ url: 'https://web.archive.org/web/20240101120000/https://example.com',
130
+ timestamp: '20240101120000',
131
+ available: true,
132
+ },
133
+ },
134
+ };
135
+ mockFetch.mockResolvedValueOnce({
136
+ ok: true,
137
+ json: async () => mockResponse,
138
+ });
139
+ const result = await client.isArchived('https://example.com');
140
+ expect(result).toBe(true);
141
+ });
142
+ it('should return false when no archive is available', async () => {
143
+ mockFetch.mockResolvedValueOnce({
144
+ ok: true,
145
+ json: async () => ({
146
+ url: 'https://example.com',
147
+ archived_snapshots: {},
148
+ }),
149
+ });
150
+ const result = await client.isArchived('https://example.com');
151
+ expect(result).toBe(false);
152
+ });
153
+ it('should return false on error', async () => {
154
+ mockFetch.mockRejectedValue(new Error('Network error'));
155
+ const fastClient = new WaybackClient({ retryDelayMs: 10, maxRetries: 0 });
156
+ const result = await fastClient.isArchived('https://example.com');
157
+ expect(result).toBe(false);
158
+ });
159
+ });
160
+ describe('getArchiveUrl', () => {
161
+ it('should return archive URL when available', async () => {
162
+ const mockResponse = {
163
+ url: 'https://example.com',
164
+ archived_snapshots: {
165
+ closest: {
166
+ url: 'https://web.archive.org/web/20240101120000/https://example.com',
167
+ timestamp: '20240101120000',
168
+ available: true,
169
+ },
170
+ },
171
+ };
172
+ mockFetch.mockResolvedValueOnce({
173
+ ok: true,
174
+ json: async () => mockResponse,
175
+ });
176
+ const result = await client.getArchiveUrl('https://example.com');
177
+ expect(result).toBe('https://web.archive.org/web/20240101120000/https://example.com');
178
+ });
179
+ it('should return null when not available', async () => {
180
+ mockFetch.mockResolvedValueOnce({
181
+ ok: true,
182
+ json: async () => ({
183
+ url: 'https://example.com',
184
+ archived_snapshots: {},
185
+ }),
186
+ });
187
+ const result = await client.getArchiveUrl('https://example.com');
188
+ expect(result).toBeNull();
189
+ });
190
+ it('should return null when available is false', async () => {
191
+ const mockResponse = {
192
+ url: 'https://example.com',
193
+ archived_snapshots: {
194
+ closest: {
195
+ url: 'https://web.archive.org/web/20240101120000/https://example.com',
196
+ timestamp: '20240101120000',
197
+ available: false,
198
+ },
199
+ },
200
+ };
201
+ mockFetch.mockResolvedValueOnce({
202
+ ok: true,
203
+ json: async () => mockResponse,
204
+ });
205
+ const result = await client.getArchiveUrl('https://example.com');
206
+ expect(result).toBeNull();
207
+ });
208
+ });
209
+ describe('createWaybackClient', () => {
210
+ it('should create a WaybackClient instance', () => {
211
+ const client = createWaybackClient();
212
+ expect(client).toBeInstanceOf(WaybackClient);
213
+ });
214
+ it('should create a WaybackClient with custom config', () => {
215
+ const client = createWaybackClient({ timeoutMs: 5000 });
216
+ expect(client).toBeInstanceOf(WaybackClient);
217
+ });
218
+ });
219
+ describe('timestamp formatting', () => {
220
+ it('should format valid timestamp to ISO 8601', async () => {
221
+ const mockResponse = {
222
+ url: 'https://example.com',
223
+ archived_snapshots: {
224
+ closest: {
225
+ url: 'https://web.archive.org/web/20231215143025/https://example.com',
226
+ timestamp: '20231215143025',
227
+ available: true,
228
+ },
229
+ },
230
+ };
231
+ mockFetch.mockResolvedValueOnce({
232
+ ok: true,
233
+ json: async () => mockResponse,
234
+ });
235
+ const result = await client.getSnapshot('https://example.com');
236
+ expect(result?.timestamp).toBe('2023-12-15T14:30:25Z');
237
+ });
238
+ it('should return invalid timestamp as-is', async () => {
239
+ const mockResponse = {
240
+ url: 'https://example.com',
241
+ archived_snapshots: {
242
+ closest: {
243
+ url: 'https://web.archive.org/web/invalid/https://example.com',
244
+ timestamp: 'invalid',
245
+ available: true,
246
+ },
247
+ },
248
+ };
249
+ mockFetch.mockResolvedValueOnce({
250
+ ok: true,
251
+ json: async () => mockResponse,
252
+ });
253
+ const result = await client.getSnapshot('https://example.com');
254
+ expect(result?.timestamp).toBe('invalid');
255
+ });
256
+ });
257
+ describe('API URL encoding', () => {
258
+ it('should properly encode URL with special characters', async () => {
259
+ mockFetch.mockResolvedValueOnce({
260
+ ok: true,
261
+ json: async () => ({
262
+ url: 'https://example.com/path?query=value&foo=bar',
263
+ archived_snapshots: {},
264
+ }),
265
+ });
266
+ await client.getSnapshot('https://example.com/path?query=value&foo=bar');
267
+ expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining(encodeURIComponent('https://example.com/path?query=value&foo=bar')), expect.any(Object));
268
+ });
269
+ });
270
+ });
271
+ //# sourceMappingURL=wayback.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wayback.test.js","sourceRoot":"","sources":["../../../../../src/tools/visit/recovery/__tests__/wayback.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * VisitRecoveryManager - ページ訪問リカバリーマネージャー
3
+ *
4
+ * TSK-1-004: VisitRecoveryManager実装
5
+ * REQ-SRCH-004-01: visit失敗時フォールバック
6
+ * REQ-SRCH-004-02: 自動リトライ
7
+ * REQ-SRCH-004-03: 結果マージ
8
+ * DES-SRCH-004: VisitRecoveryManager設計
9
+ */
10
+ import { WaybackClient, type WaybackSnapshot, type WaybackClientConfig } from './wayback.js';
11
+ import { RecoveryLogger, type RecoveryLoggerConfig } from '../../search/recovery/logger.js';
12
+ /**
13
+ * ページ取得関数の型
14
+ */
15
+ export type FetchFunction = (url: string) => Promise<PageFetchResult>;
16
+ /**
17
+ * ページ取得結果
18
+ */
19
+ export interface PageFetchResult {
20
+ /** 取得に成功したかどうか */
21
+ success: boolean;
22
+ /** コンテンツ(成功時) */
23
+ content?: string;
24
+ /** タイトル(成功時) */
25
+ title?: string;
26
+ /** エラーメッセージ(失敗時) */
27
+ error?: string;
28
+ /** HTTPステータスコード */
29
+ statusCode?: number;
30
+ }
31
+ /**
32
+ * リカバリー結果
33
+ */
34
+ export interface VisitRecoveryResult {
35
+ /** 最終的に成功したかどうか */
36
+ success: boolean;
37
+ /** 元のURL */
38
+ originalUrl: string;
39
+ /** 実際に取得したURL(Wayback URLの可能性あり) */
40
+ usedUrl: string;
41
+ /** コンテンツ(成功時) */
42
+ content?: string;
43
+ /** タイトル(成功時) */
44
+ title?: string;
45
+ /** エラーメッセージ(失敗時) */
46
+ error?: string;
47
+ /** Wayback Machineを使用したかどうか */
48
+ usedWayback: boolean;
49
+ /** Waybackスナップショット情報 */
50
+ waybackSnapshot?: WaybackSnapshot;
51
+ /** 試行回数 */
52
+ attempts: number;
53
+ /** 処理時間(ms) */
54
+ durationMs: number;
55
+ }
56
+ /**
57
+ * VisitRecoveryManager 設定
58
+ */
59
+ export interface VisitRecoveryConfig {
60
+ /** 最大リトライ回数(デフォルト: 2) */
61
+ maxRetries?: number;
62
+ /** リトライ間隔(ms、デフォルト: 1000) */
63
+ retryDelayMs?: number;
64
+ /** タイムアウト(ms、デフォルト: 30000) */
65
+ timeoutMs?: number;
66
+ /** Wayback Machineを使用するかどうか(デフォルト: true) */
67
+ enableWayback?: boolean;
68
+ /** WaybackClient設定 */
69
+ waybackConfig?: Partial<WaybackClientConfig>;
70
+ /** RecoveryLogger設定 */
71
+ loggerConfig?: Partial<RecoveryLoggerConfig>;
72
+ /** RecoveryLoggerインスタンス(省略時は新規作成) */
73
+ logger?: RecoveryLogger;
74
+ }
75
+ /**
76
+ * デフォルト設定
77
+ */
78
+ export declare const DEFAULT_VISIT_RECOVERY_CONFIG: Required<Omit<VisitRecoveryConfig, 'waybackConfig' | 'loggerConfig' | 'logger'>>;
79
+ /**
80
+ * VisitRecoveryManager - ページ訪問失敗時の自動リカバリー
81
+ */
82
+ export declare class VisitRecoveryManager {
83
+ private readonly config;
84
+ private readonly waybackClient;
85
+ private readonly logger;
86
+ constructor(config?: VisitRecoveryConfig);
87
+ /**
88
+ * リカバリー付きページ取得を実行
89
+ * @param url 取得対象のURL
90
+ * @param fetchFn ページ取得関数
91
+ */
92
+ recover(url: string, fetchFn: FetchFunction): Promise<VisitRecoveryResult>;
93
+ /**
94
+ * Wayback Machineを使用してリカバリーを試行
95
+ */
96
+ private tryWayback;
97
+ /**
98
+ * タイムアウト付きでページ取得を実行
99
+ */
100
+ private fetchWithTimeout;
101
+ /**
102
+ * リカバリー試行をログに記録
103
+ */
104
+ private logAttempt;
105
+ /**
106
+ * 指定時間待機
107
+ */
108
+ private delay;
109
+ /**
110
+ * RecoveryLoggerインスタンスを取得
111
+ */
112
+ getLogger(): RecoveryLogger;
113
+ /**
114
+ * 統計情報を取得
115
+ */
116
+ getStats(): ReturnType<RecoveryLogger['getStats']>;
117
+ /**
118
+ * WaybackClientインスタンスを取得
119
+ */
120
+ getWaybackClient(): WaybackClient | null;
121
+ }
122
+ /**
123
+ * VisitRecoveryManagerのファクトリ関数
124
+ */
125
+ export declare function createVisitRecoveryManager(config?: VisitRecoveryConfig): VisitRecoveryManager;
126
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/tools/visit/recovery/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,203 @@
1
+ /**
2
+ * VisitRecoveryManager - ページ訪問リカバリーマネージャー
3
+ *
4
+ * TSK-1-004: VisitRecoveryManager実装
5
+ * REQ-SRCH-004-01: visit失敗時フォールバック
6
+ * REQ-SRCH-004-02: 自動リトライ
7
+ * REQ-SRCH-004-03: 結果マージ
8
+ * DES-SRCH-004: VisitRecoveryManager設計
9
+ */
10
+ import { WaybackClient } from './wayback.js';
11
+ import { RecoveryLogger } from '../../search/recovery/logger.js';
12
+ /**
13
+ * デフォルト設定
14
+ */
15
+ export const DEFAULT_VISIT_RECOVERY_CONFIG = {
16
+ maxRetries: 2,
17
+ retryDelayMs: 1000,
18
+ timeoutMs: 30000,
19
+ enableWayback: true,
20
+ };
21
+ /**
22
+ * VisitRecoveryManager - ページ訪問失敗時の自動リカバリー
23
+ */
24
+ export class VisitRecoveryManager {
25
+ config;
26
+ waybackClient;
27
+ logger;
28
+ constructor(config) {
29
+ const { waybackConfig, loggerConfig, logger, ...restConfig } = config ?? {};
30
+ this.config = { ...DEFAULT_VISIT_RECOVERY_CONFIG, ...restConfig };
31
+ this.waybackClient = this.config.enableWayback ? new WaybackClient(waybackConfig) : null;
32
+ this.logger = logger ?? new RecoveryLogger(loggerConfig);
33
+ }
34
+ /**
35
+ * リカバリー付きページ取得を実行
36
+ * @param url 取得対象のURL
37
+ * @param fetchFn ページ取得関数
38
+ */
39
+ async recover(url, fetchFn) {
40
+ const startTime = Date.now();
41
+ let attempts = 0;
42
+ let lastError;
43
+ // 1. 元のURLでリトライ
44
+ for (let i = 0; i <= this.config.maxRetries; i++) {
45
+ attempts++;
46
+ const attemptStart = Date.now();
47
+ try {
48
+ const result = await this.fetchWithTimeout(fetchFn, url);
49
+ const durationMs = Date.now() - attemptStart;
50
+ if (result.success) {
51
+ this.logAttempt(url, url, 'direct', true, durationMs);
52
+ return {
53
+ success: true,
54
+ originalUrl: url,
55
+ usedUrl: url,
56
+ content: result.content,
57
+ title: result.title,
58
+ usedWayback: false,
59
+ attempts,
60
+ durationMs: Date.now() - startTime,
61
+ };
62
+ }
63
+ lastError = result.error ?? 'Unknown error';
64
+ this.logAttempt(url, url, 'direct', false, durationMs, lastError);
65
+ }
66
+ catch (error) {
67
+ const durationMs = Date.now() - attemptStart;
68
+ lastError = error instanceof Error ? error.message : String(error);
69
+ this.logAttempt(url, url, 'direct', false, durationMs, lastError);
70
+ }
71
+ // リトライ前に待機
72
+ if (i < this.config.maxRetries) {
73
+ await this.delay(this.config.retryDelayMs);
74
+ }
75
+ }
76
+ // 2. Wayback Machineを使用してリカバリー
77
+ if (this.waybackClient) {
78
+ const waybackResult = await this.tryWayback(url, fetchFn, startTime, attempts);
79
+ if (waybackResult) {
80
+ return waybackResult;
81
+ }
82
+ }
83
+ // 3. すべての試行が失敗
84
+ return {
85
+ success: false,
86
+ originalUrl: url,
87
+ usedUrl: url,
88
+ error: lastError ?? 'All recovery attempts failed',
89
+ usedWayback: false,
90
+ attempts,
91
+ durationMs: Date.now() - startTime,
92
+ };
93
+ }
94
+ /**
95
+ * Wayback Machineを使用してリカバリーを試行
96
+ */
97
+ async tryWayback(originalUrl, fetchFn, startTime, currentAttempts) {
98
+ if (!this.waybackClient) {
99
+ return null;
100
+ }
101
+ const waybackAttemptStart = Date.now();
102
+ const snapshot = await this.waybackClient.getSnapshot(originalUrl);
103
+ if (!snapshot?.available) {
104
+ this.logAttempt(originalUrl, originalUrl, 'wayback-check', false, Date.now() - waybackAttemptStart, 'No archive available');
105
+ return null;
106
+ }
107
+ const attemptStart = Date.now();
108
+ try {
109
+ const result = await this.fetchWithTimeout(fetchFn, snapshot.url);
110
+ const durationMs = Date.now() - attemptStart;
111
+ if (result.success) {
112
+ this.logAttempt(originalUrl, snapshot.url, 'wayback', true, durationMs);
113
+ return {
114
+ success: true,
115
+ originalUrl,
116
+ usedUrl: snapshot.url,
117
+ content: result.content,
118
+ title: result.title,
119
+ usedWayback: true,
120
+ waybackSnapshot: snapshot,
121
+ attempts: currentAttempts + 1,
122
+ durationMs: Date.now() - startTime,
123
+ };
124
+ }
125
+ this.logAttempt(originalUrl, snapshot.url, 'wayback', false, durationMs, result.error);
126
+ }
127
+ catch (error) {
128
+ const durationMs = Date.now() - attemptStart;
129
+ const errorMsg = error instanceof Error ? error.message : String(error);
130
+ this.logAttempt(originalUrl, snapshot.url, 'wayback', false, durationMs, errorMsg);
131
+ }
132
+ return null;
133
+ }
134
+ /**
135
+ * タイムアウト付きでページ取得を実行
136
+ */
137
+ async fetchWithTimeout(fetchFn, url) {
138
+ return new Promise((resolve, reject) => {
139
+ const timer = setTimeout(() => {
140
+ reject(new Error(`Request timed out after ${this.config.timeoutMs}ms`));
141
+ }, this.config.timeoutMs);
142
+ fetchFn(url)
143
+ .then((result) => {
144
+ clearTimeout(timer);
145
+ resolve(result);
146
+ })
147
+ .catch((error) => {
148
+ clearTimeout(timer);
149
+ reject(error);
150
+ });
151
+ });
152
+ }
153
+ /**
154
+ * リカバリー試行をログに記録
155
+ */
156
+ logAttempt(originalUrl, usedUrl, strategy, success, durationMs, error) {
157
+ const entry = {
158
+ originalQuery: originalUrl,
159
+ alternativeQuery: usedUrl,
160
+ strategy,
161
+ resultCount: success ? 1 : 0,
162
+ success,
163
+ timestamp: new Date(),
164
+ durationMs,
165
+ type: 'visit',
166
+ error,
167
+ };
168
+ this.logger.log(entry);
169
+ // stderr にログ出力
170
+ console.error(`[VisitRecovery] ${success ? '✓' : '✗'} "${originalUrl}" ${usedUrl !== originalUrl ? `→ "${usedUrl}"` : ''} (${strategy}) ${durationMs}ms`);
171
+ }
172
+ /**
173
+ * 指定時間待機
174
+ */
175
+ delay(ms) {
176
+ return new Promise((resolve) => setTimeout(resolve, ms));
177
+ }
178
+ /**
179
+ * RecoveryLoggerインスタンスを取得
180
+ */
181
+ getLogger() {
182
+ return this.logger;
183
+ }
184
+ /**
185
+ * 統計情報を取得
186
+ */
187
+ getStats() {
188
+ return this.logger.getStats();
189
+ }
190
+ /**
191
+ * WaybackClientインスタンスを取得
192
+ */
193
+ getWaybackClient() {
194
+ return this.waybackClient;
195
+ }
196
+ }
197
+ /**
198
+ * VisitRecoveryManagerのファクトリ関数
199
+ */
200
+ export function createVisitRecoveryManager(config) {
201
+ return new VisitRecoveryManager(config);
202
+ }
203
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/tools/visit/recovery/index.ts"],"names":[],"mappings":"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"}