@deimoscloud/coreai 0.1.8 → 0.1.10

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 (196) hide show
  1. package/dist/cli/index.js +5 -0
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/index.js +3 -1
  4. package/dist/index.js.map +1 -1
  5. package/package.json +6 -1
  6. package/.prettierrc +0 -9
  7. package/AGENT_SPEC.md +0 -347
  8. package/ARCHITECTURE.md +0 -547
  9. package/DRAFT_PRD.md +0 -1440
  10. package/IMPLEMENTATION_PLAN.md +0 -256
  11. package/PRODUCT.md +0 -473
  12. package/WORKFLOWS.md +0 -295
  13. package/commands/core/check-inbox.md +0 -34
  14. package/commands/core/delegate.md +0 -30
  15. package/commands/core/git-commit.md +0 -144
  16. package/commands/core/pr-create.md +0 -193
  17. package/commands/core/review.md +0 -56
  18. package/commands/core/sprint-status.md +0 -65
  19. package/commands/optional/docs-update.md +0 -200
  20. package/commands/optional/jira-create.md +0 -200
  21. package/commands/optional/jira-transition.md +0 -184
  22. package/commands/optional/worktree-cleanup.md +0 -167
  23. package/commands/optional/worktree-setup.md +0 -110
  24. package/eslint.config.js +0 -29
  25. package/jest.config.js +0 -22
  26. package/knowledge-library/README.md +0 -118
  27. package/knowledge-library/android-engineer/context/current.txt +0 -42
  28. package/knowledge-library/android-engineer/control/decisions.txt +0 -9
  29. package/knowledge-library/android-engineer/control/dependencies.txt +0 -19
  30. package/knowledge-library/android-engineer/control/objectives.txt +0 -26
  31. package/knowledge-library/android-engineer/history/.gitkeep +0 -0
  32. package/knowledge-library/android-engineer/inbox/processed/.gitkeep +0 -0
  33. package/knowledge-library/android-engineer/outbox/.gitkeep +0 -0
  34. package/knowledge-library/android-engineer/tech/.gitkeep +0 -0
  35. package/knowledge-library/architecture.txt +0 -61
  36. package/knowledge-library/backend-engineer/context/current.txt +0 -42
  37. package/knowledge-library/backend-engineer/control/decisions.txt +0 -9
  38. package/knowledge-library/backend-engineer/control/dependencies.txt +0 -19
  39. package/knowledge-library/backend-engineer/control/objectives.txt +0 -26
  40. package/knowledge-library/backend-engineer/history/.gitkeep +0 -0
  41. package/knowledge-library/backend-engineer/inbox/processed/.gitkeep +0 -0
  42. package/knowledge-library/backend-engineer/outbox/.gitkeep +0 -0
  43. package/knowledge-library/backend-engineer/tech/.gitkeep +0 -0
  44. package/knowledge-library/context.txt +0 -52
  45. package/knowledge-library/devops-engineer/context/current.txt +0 -42
  46. package/knowledge-library/devops-engineer/control/decisions.txt +0 -9
  47. package/knowledge-library/devops-engineer/control/dependencies.txt +0 -19
  48. package/knowledge-library/devops-engineer/control/objectives.txt +0 -26
  49. package/knowledge-library/devops-engineer/history/.gitkeep +0 -0
  50. package/knowledge-library/devops-engineer/inbox/processed/.gitkeep +0 -0
  51. package/knowledge-library/devops-engineer/outbox/.gitkeep +0 -0
  52. package/knowledge-library/devops-engineer/tech/.gitkeep +0 -0
  53. package/knowledge-library/engineering-manager/context/current.txt +0 -40
  54. package/knowledge-library/engineering-manager/control/decisions.txt +0 -9
  55. package/knowledge-library/engineering-manager/control/objectives.txt +0 -27
  56. package/knowledge-library/engineering-manager/history/.gitkeep +0 -0
  57. package/knowledge-library/engineering-manager/inbox/processed/.gitkeep +0 -0
  58. package/knowledge-library/engineering-manager/outbox/.gitkeep +0 -0
  59. package/knowledge-library/engineering-manager/tech/.gitkeep +0 -0
  60. package/knowledge-library/prd.txt +0 -81
  61. package/knowledge-library/product-manager/context/current.txt +0 -42
  62. package/knowledge-library/product-manager/control/decisions.txt +0 -9
  63. package/knowledge-library/product-manager/control/dependencies.txt +0 -19
  64. package/knowledge-library/product-manager/control/objectives.txt +0 -26
  65. package/knowledge-library/product-manager/history/.gitkeep +0 -0
  66. package/knowledge-library/product-manager/inbox/processed/.gitkeep +0 -0
  67. package/knowledge-library/product-manager/outbox/.gitkeep +0 -0
  68. package/knowledge-library/product-manager/tech/.gitkeep +0 -0
  69. package/knowledge-library/qa-engineer/context/current.txt +0 -42
  70. package/knowledge-library/qa-engineer/control/decisions.txt +0 -9
  71. package/knowledge-library/qa-engineer/control/dependencies.txt +0 -19
  72. package/knowledge-library/qa-engineer/control/objectives.txt +0 -26
  73. package/knowledge-library/qa-engineer/history/.gitkeep +0 -0
  74. package/knowledge-library/qa-engineer/inbox/processed/.gitkeep +0 -0
  75. package/knowledge-library/qa-engineer/outbox/.gitkeep +0 -0
  76. package/knowledge-library/qa-engineer/tech/.gitkeep +0 -0
  77. package/knowledge-library/security-engineer/context/current.txt +0 -42
  78. package/knowledge-library/security-engineer/control/decisions.txt +0 -9
  79. package/knowledge-library/security-engineer/control/dependencies.txt +0 -19
  80. package/knowledge-library/security-engineer/control/objectives.txt +0 -26
  81. package/knowledge-library/security-engineer/history/.gitkeep +0 -0
  82. package/knowledge-library/security-engineer/inbox/processed/.gitkeep +0 -0
  83. package/knowledge-library/security-engineer/outbox/.gitkeep +0 -0
  84. package/knowledge-library/security-engineer/tech/.gitkeep +0 -0
  85. package/knowledge-library/solutions-architect/context/current.txt +0 -42
  86. package/knowledge-library/solutions-architect/control/decisions.txt +0 -9
  87. package/knowledge-library/solutions-architect/control/dependencies.txt +0 -19
  88. package/knowledge-library/solutions-architect/control/objectives.txt +0 -26
  89. package/knowledge-library/solutions-architect/history/.gitkeep +0 -0
  90. package/knowledge-library/solutions-architect/inbox/processed/.gitkeep +0 -0
  91. package/knowledge-library/solutions-architect/outbox/.gitkeep +0 -0
  92. package/knowledge-library/solutions-architect/tech/.gitkeep +0 -0
  93. package/knowledge-library/wearos-engineer/context/current.txt +0 -42
  94. package/knowledge-library/wearos-engineer/control/decisions.txt +0 -9
  95. package/knowledge-library/wearos-engineer/control/dependencies.txt +0 -19
  96. package/knowledge-library/wearos-engineer/control/objectives.txt +0 -26
  97. package/knowledge-library/wearos-engineer/history/.gitkeep +0 -0
  98. package/knowledge-library/wearos-engineer/inbox/processed/.gitkeep +0 -0
  99. package/knowledge-library/wearos-engineer/outbox/.gitkeep +0 -0
  100. package/knowledge-library/wearos-engineer/tech/.gitkeep +0 -0
  101. package/scripts/add-agent.sh +0 -323
  102. package/scripts/install.sh +0 -354
  103. package/src/adapters/factory.test.ts +0 -386
  104. package/src/adapters/factory.ts +0 -305
  105. package/src/adapters/index.ts +0 -113
  106. package/src/adapters/interfaces.ts +0 -268
  107. package/src/adapters/mcp/client.test.ts +0 -130
  108. package/src/adapters/mcp/client.ts +0 -451
  109. package/src/adapters/mcp/discovery.test.ts +0 -315
  110. package/src/adapters/mcp/discovery.ts +0 -340
  111. package/src/adapters/mcp/index.ts +0 -66
  112. package/src/adapters/mcp/mapper.test.ts +0 -218
  113. package/src/adapters/mcp/mapper.ts +0 -536
  114. package/src/adapters/mcp/registry.test.ts +0 -433
  115. package/src/adapters/mcp/registry.ts +0 -550
  116. package/src/adapters/mcp/types.ts +0 -258
  117. package/src/adapters/native/filesystem.test.ts +0 -350
  118. package/src/adapters/native/filesystem.ts +0 -393
  119. package/src/adapters/native/github.test.ts +0 -173
  120. package/src/adapters/native/github.ts +0 -627
  121. package/src/adapters/native/index.ts +0 -22
  122. package/src/adapters/native/selector.test.ts +0 -224
  123. package/src/adapters/native/selector.ts +0 -150
  124. package/src/adapters/types.ts +0 -270
  125. package/src/agents/compiler.test.ts +0 -399
  126. package/src/agents/compiler.ts +0 -422
  127. package/src/agents/index.ts +0 -37
  128. package/src/agents/loader.test.ts +0 -319
  129. package/src/agents/loader.ts +0 -143
  130. package/src/agents/resolver.test.ts +0 -282
  131. package/src/agents/resolver.ts +0 -262
  132. package/src/agents/types.ts +0 -97
  133. package/src/cache/index.ts +0 -38
  134. package/src/cache/interfaces.ts +0 -283
  135. package/src/cache/manager.test.ts +0 -266
  136. package/src/cache/manager.ts +0 -388
  137. package/src/cache/provider.test.ts +0 -485
  138. package/src/cache/provider.ts +0 -745
  139. package/src/cache/types.test.ts +0 -192
  140. package/src/cache/types.ts +0 -313
  141. package/src/cli/commands/build.test.ts +0 -248
  142. package/src/cli/commands/build.ts +0 -284
  143. package/src/cli/commands/cache.test.ts +0 -221
  144. package/src/cli/commands/cache.ts +0 -229
  145. package/src/cli/commands/index.ts +0 -63
  146. package/src/cli/commands/init.test.ts +0 -173
  147. package/src/cli/commands/init.ts +0 -296
  148. package/src/cli/commands/skills.test.ts +0 -272
  149. package/src/cli/commands/skills.ts +0 -348
  150. package/src/cli/commands/status.test.ts +0 -392
  151. package/src/cli/commands/status.ts +0 -332
  152. package/src/cli/commands/sync.test.ts +0 -213
  153. package/src/cli/commands/sync.ts +0 -251
  154. package/src/cli/commands/validate.test.ts +0 -216
  155. package/src/cli/commands/validate.ts +0 -340
  156. package/src/cli/index.test.ts +0 -190
  157. package/src/cli/index.ts +0 -493
  158. package/src/commands/context.test.ts +0 -163
  159. package/src/commands/context.ts +0 -111
  160. package/src/commands/index.ts +0 -56
  161. package/src/commands/loader.test.ts +0 -273
  162. package/src/commands/loader.ts +0 -355
  163. package/src/commands/registry.test.ts +0 -384
  164. package/src/commands/registry.ts +0 -248
  165. package/src/commands/runner.test.ts +0 -297
  166. package/src/commands/runner.ts +0 -222
  167. package/src/commands/types.ts +0 -361
  168. package/src/config/index.ts +0 -19
  169. package/src/config/loader.test.ts +0 -262
  170. package/src/config/loader.ts +0 -188
  171. package/src/config/types.ts +0 -154
  172. package/src/context/index.ts +0 -14
  173. package/src/context/loader.test.ts +0 -334
  174. package/src/context/loader.ts +0 -357
  175. package/src/index.test.ts +0 -13
  176. package/src/index.ts +0 -268
  177. package/src/knowledge-library/index.ts +0 -44
  178. package/src/knowledge-library/manager.test.ts +0 -536
  179. package/src/knowledge-library/manager.ts +0 -804
  180. package/src/knowledge-library/types.ts +0 -432
  181. package/src/skills/generator.test.ts +0 -602
  182. package/src/skills/generator.ts +0 -491
  183. package/src/skills/index.ts +0 -27
  184. package/src/skills/templates.ts +0 -520
  185. package/src/skills/types.ts +0 -251
  186. package/templates/completion-report.md +0 -72
  187. package/templates/feedback.md +0 -56
  188. package/templates/project-files/CLAUDE.md.template +0 -109
  189. package/templates/project-files/coreai.json.example +0 -47
  190. package/templates/project-files/mcp.json.template +0 -20
  191. package/templates/review-complete.md +0 -64
  192. package/templates/review-request.md +0 -67
  193. package/templates/task-assignment.md +0 -51
  194. package/tsconfig.build.json +0 -4
  195. package/tsconfig.json +0 -26
  196. package/tsup.config.ts +0 -23
@@ -1,283 +0,0 @@
1
- /**
2
- * Cache Interfaces
3
- *
4
- * Interface definitions for the cache system.
5
- */
6
-
7
- import type {
8
- CacheEntry,
9
- CacheMetadata,
10
- CacheOptions,
11
- CacheListOptions,
12
- CacheStats,
13
- CacheStatus,
14
- SyncResult,
15
- } from './types.js';
16
-
17
- /**
18
- * Cache provider interface
19
- *
20
- * Defines the contract for cache implementations.
21
- */
22
- export interface CacheProvider {
23
- /**
24
- * Initialize the cache (create directories, load index)
25
- */
26
- initialize(): Promise<void>;
27
-
28
- /**
29
- * Check if the cache is initialized
30
- */
31
- isInitialized(): boolean;
32
-
33
- /**
34
- * Get a cached entry by key
35
- *
36
- * @param key - Cache key
37
- * @param options - Optional cache options
38
- * @returns The cached entry or null if not found/expired
39
- */
40
- get<T = string>(key: string, options?: CacheOptions): Promise<CacheEntry<T> | null>;
41
-
42
- /**
43
- * Get the content only (convenience method)
44
- *
45
- * @param key - Cache key
46
- * @param options - Optional cache options
47
- * @returns The cached content or null if not found/expired
48
- */
49
- getContent<T = string>(key: string, options?: CacheOptions): Promise<T | null>;
50
-
51
- /**
52
- * Set a cache entry
53
- *
54
- * @param key - Cache key
55
- * @param content - Content to cache
56
- * @param metadata - Partial metadata (key and cachedAt will be set automatically)
57
- * @param options - Optional cache options
58
- */
59
- set<T = string>(
60
- key: string,
61
- content: T,
62
- metadata: Partial<CacheMetadata>,
63
- options?: CacheOptions
64
- ): Promise<void>;
65
-
66
- /**
67
- * Check if a key exists in the cache
68
- *
69
- * @param key - Cache key
70
- * @returns True if the key exists (regardless of expiration)
71
- */
72
- has(key: string): Promise<boolean>;
73
-
74
- /**
75
- * Delete a cache entry
76
- *
77
- * @param key - Cache key
78
- * @returns True if the entry was deleted
79
- */
80
- delete(key: string): Promise<boolean>;
81
-
82
- /**
83
- * Get the status of a cache entry
84
- *
85
- * @param key - Cache key
86
- * @returns The cache status or null if not found
87
- */
88
- getStatus(key: string): Promise<CacheStatus | null>;
89
-
90
- /**
91
- * Get metadata for a cache entry
92
- *
93
- * @param key - Cache key
94
- * @returns The metadata or null if not found
95
- */
96
- getMetadata(key: string): Promise<CacheMetadata | null>;
97
-
98
- /**
99
- * Update metadata for a cache entry
100
- *
101
- * @param key - Cache key
102
- * @param metadata - Partial metadata to update
103
- */
104
- updateMetadata(key: string, metadata: Partial<CacheMetadata>): Promise<void>;
105
-
106
- /**
107
- * List cache entries
108
- *
109
- * @param options - List filter options
110
- * @returns Array of metadata entries
111
- */
112
- list(options?: CacheListOptions): Promise<CacheMetadata[]>;
113
-
114
- /**
115
- * Get cache statistics
116
- */
117
- getStats(): Promise<CacheStats>;
118
-
119
- /**
120
- * Clear all cache entries
121
- *
122
- * @returns Number of entries cleared
123
- */
124
- clear(): Promise<number>;
125
-
126
- /**
127
- * Clear expired entries only
128
- *
129
- * @returns Number of entries cleared
130
- */
131
- clearExpired(): Promise<number>;
132
-
133
- /**
134
- * Clear entries by source
135
- *
136
- * @param source - Source to clear
137
- * @returns Number of entries cleared
138
- */
139
- clearBySource(source: string): Promise<number>;
140
-
141
- /**
142
- * Clear entries by tag
143
- *
144
- * @param tag - Tag to clear
145
- * @returns Number of entries cleared
146
- */
147
- clearByTag(tag: string): Promise<number>;
148
- }
149
-
150
- /**
151
- * Remote fetcher interface
152
- *
153
- * Used by the cache to fetch content from remote sources.
154
- */
155
- export interface RemoteFetcher {
156
- /**
157
- * Fetch content from a remote source
158
- *
159
- * @param url - Source URL or identifier
160
- * @param options - Fetch options
161
- * @returns The fetched content and metadata
162
- */
163
- fetch(
164
- url: string,
165
- options?: FetchOptions
166
- ): Promise<{ content: string; metadata: Partial<CacheMetadata> }>;
167
-
168
- /**
169
- * Check if content has changed (conditional fetch)
170
- *
171
- * @param url - Source URL or identifier
172
- * @param etag - Previous ETag
173
- * @returns True if content has changed
174
- */
175
- hasChanged(url: string, etag?: string): Promise<boolean>;
176
- }
177
-
178
- /**
179
- * Options for remote fetching
180
- */
181
- export interface FetchOptions {
182
- /**
183
- * Request timeout in milliseconds
184
- */
185
- timeout?: number;
186
-
187
- /**
188
- * ETag for conditional fetching
189
- */
190
- etag?: string;
191
-
192
- /**
193
- * Custom headers
194
- */
195
- headers?: Record<string, string>;
196
- }
197
-
198
- /**
199
- * Cache manager interface
200
- *
201
- * Higher-level interface that combines caching with remote fetching.
202
- */
203
- export interface CacheManager {
204
- /**
205
- * Get content with cache-first strategy
206
- *
207
- * 1. Check cache
208
- * 2. If cached and valid, return cached content
209
- * 3. If stale or missing, fetch from remote
210
- * 4. Cache the fetched content
211
- * 5. Return the content
212
- *
213
- * @param key - Cache key
214
- * @param url - Remote URL to fetch if not cached
215
- * @param options - Cache and fetch options
216
- */
217
- getWithFallback<T = string>(
218
- key: string,
219
- url: string,
220
- options?: CacheOptions & FetchOptions
221
- ): Promise<CacheEntry<T>>;
222
-
223
- /**
224
- * Sync all entries from a source
225
- *
226
- * @param source - Source to sync
227
- * @param options - Sync options
228
- */
229
- syncSource(source: string, options?: SyncOptions): Promise<SyncResult>;
230
-
231
- /**
232
- * Sync specific entries
233
- *
234
- * @param keys - Keys to sync
235
- * @param options - Sync options
236
- */
237
- syncEntries(keys: string[], options?: SyncOptions): Promise<SyncResult>;
238
-
239
- /**
240
- * Register a fetcher for a source
241
- *
242
- * @param source - Source identifier
243
- * @param fetcher - Fetcher implementation
244
- */
245
- registerFetcher(source: string, fetcher: RemoteFetcher): void;
246
-
247
- /**
248
- * Check if a fetcher is registered for a source
249
- *
250
- * @param source - Source identifier
251
- */
252
- hasFetcher(source: string): boolean;
253
-
254
- /**
255
- * Get the underlying cache provider
256
- */
257
- getCache(): CacheProvider;
258
- }
259
-
260
- /**
261
- * Options for sync operations
262
- */
263
- export interface SyncOptions {
264
- /**
265
- * Force refresh all entries
266
- */
267
- force?: boolean;
268
-
269
- /**
270
- * Continue on error
271
- */
272
- continueOnError?: boolean;
273
-
274
- /**
275
- * Maximum concurrent fetches
276
- */
277
- concurrency?: number;
278
-
279
- /**
280
- * Progress callback
281
- */
282
- onProgress?: (completed: number, total: number) => void;
283
- }
@@ -1,266 +0,0 @@
1
- /**
2
- * Cache Manager Tests
3
- */
4
-
5
- import { promises as fs } from 'fs';
6
- import { join } from 'path';
7
- import { tmpdir } from 'os';
8
- import { CacheManager, createCacheManager } from './manager.js';
9
- import { FileCacheProvider } from './provider.js';
10
- import { CacheError } from './types.js';
11
- import type { RemoteFetcher } from './index.js';
12
-
13
- describe('CacheManager', () => {
14
- let testDir: string;
15
- let cacheProvider: FileCacheProvider;
16
- let manager: CacheManager;
17
-
18
- // Mock fetcher for testing
19
- const createMockFetcher = (responses: Record<string, string>): RemoteFetcher => ({
20
- async fetch(url: string) {
21
- const content = responses[url];
22
- if (!content) {
23
- throw new Error(`Not found: ${url}`);
24
- }
25
- return {
26
- content,
27
- metadata: {
28
- contentType: 'text/plain',
29
- etag: `etag-${url}`,
30
- title: `Title for ${url}`,
31
- },
32
- };
33
- },
34
- async hasChanged(_url: string, _etag?: string) {
35
- return true; // Always changed for testing
36
- },
37
- });
38
-
39
- beforeEach(async () => {
40
- testDir = join(tmpdir(), `manager-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
41
- await fs.mkdir(testDir, { recursive: true });
42
-
43
- cacheProvider = new FileCacheProvider({ basePath: testDir });
44
- await cacheProvider.initialize();
45
-
46
- manager = new CacheManager({
47
- cache: cacheProvider,
48
- defaultTtl: 3600,
49
- });
50
- });
51
-
52
- afterEach(async () => {
53
- try {
54
- await fs.rm(testDir, { recursive: true, force: true });
55
- } catch {
56
- // Ignore cleanup errors
57
- }
58
- });
59
-
60
- describe('constructor', () => {
61
- it('should create manager with options', () => {
62
- expect(manager).toBeInstanceOf(CacheManager);
63
- });
64
-
65
- it('should use default values', () => {
66
- const m = new CacheManager({ cache: cacheProvider });
67
- expect(m).toBeInstanceOf(CacheManager);
68
- });
69
- });
70
-
71
- describe('registerFetcher', () => {
72
- it('should register a fetcher', () => {
73
- const fetcher = createMockFetcher({});
74
- manager.registerFetcher('github', fetcher);
75
- expect(manager.hasFetcher('github')).toBe(true);
76
- });
77
-
78
- it('should track registered sources', () => {
79
- manager.registerFetcher('github', createMockFetcher({}));
80
- manager.registerFetcher('confluence', createMockFetcher({}));
81
-
82
- const sources = manager.getRegisteredSources();
83
- expect(sources).toContain('github');
84
- expect(sources).toContain('confluence');
85
- });
86
- });
87
-
88
- describe('getWithFallback', () => {
89
- it('should fetch and cache content', async () => {
90
- const fetcher = createMockFetcher({
91
- 'https://github.com/test': 'GitHub content',
92
- });
93
- manager.registerFetcher('github', fetcher);
94
-
95
- const entry = await manager.getWithFallback('test-key', 'https://github.com/test');
96
-
97
- expect(entry.content).toBe('GitHub content');
98
- expect(entry.metadata.source).toBe('github');
99
- });
100
-
101
- it('should return cached content on second call', async () => {
102
- const responses = { 'https://github.com/test': 'Original content' };
103
- const fetcher = createMockFetcher(responses);
104
- manager.registerFetcher('github', fetcher);
105
-
106
- // First call - fetches
107
- await manager.getWithFallback('cached-key', 'https://github.com/test');
108
-
109
- // Change the response
110
- responses['https://github.com/test'] = 'Updated content';
111
-
112
- // Second call - should return cached
113
- const entry = await manager.getWithFallback('cached-key', 'https://github.com/test');
114
- expect(entry.content).toBe('Original content');
115
- });
116
-
117
- it('should force refresh when option set', async () => {
118
- const responses = { 'https://github.com/test': 'Original content' };
119
- const fetcher = createMockFetcher(responses);
120
- manager.registerFetcher('github', fetcher);
121
-
122
- await manager.getWithFallback('force-key', 'https://github.com/test');
123
-
124
- responses['https://github.com/test'] = 'Updated content';
125
-
126
- const entry = await manager.getWithFallback('force-key', 'https://github.com/test', {
127
- forceRefresh: true,
128
- });
129
- expect(entry.content).toBe('Updated content');
130
- });
131
-
132
- it('should throw if no fetcher registered', async () => {
133
- await expect(manager.getWithFallback('key', 'https://unknown.com/test')).rejects.toThrow(
134
- CacheError
135
- );
136
- });
137
-
138
- it('should skip cache when option set', async () => {
139
- const responses = { 'https://github.com/test': 'Content' };
140
- const fetcher = createMockFetcher(responses);
141
- manager.registerFetcher('github', fetcher);
142
-
143
- // Cache something first
144
- await manager.getWithFallback('skip-key', 'https://github.com/test');
145
-
146
- responses['https://github.com/test'] = 'New content';
147
-
148
- // Skip cache should fetch new content
149
- const entry = await manager.getWithFallback('skip-key', 'https://github.com/test', {
150
- skipCache: true,
151
- });
152
- expect(entry.content).toBe('New content');
153
- });
154
-
155
- it('should apply tags to cached entry', async () => {
156
- const fetcher = createMockFetcher({
157
- 'https://github.com/test': 'Content',
158
- });
159
- manager.registerFetcher('github', fetcher);
160
-
161
- await manager.getWithFallback('tagged-key', 'https://github.com/test', {
162
- tags: ['docs', 'api'],
163
- });
164
-
165
- const metadata = await cacheProvider.getMetadata('tagged-key');
166
- expect(metadata?.tags).toEqual(['docs', 'api']);
167
- });
168
- });
169
-
170
- describe('getCache', () => {
171
- it('should return the underlying cache provider', () => {
172
- const cache = manager.getCache();
173
- expect(cache).toBe(cacheProvider);
174
- });
175
- });
176
-
177
- describe('hasFetcher', () => {
178
- it('should return false for unregistered source', () => {
179
- expect(manager.hasFetcher('unknown')).toBe(false);
180
- });
181
-
182
- it('should return true for registered source', () => {
183
- manager.registerFetcher('test', createMockFetcher({}));
184
- expect(manager.hasFetcher('test')).toBe(true);
185
- });
186
- });
187
-
188
- describe('source detection', () => {
189
- it('should detect GitHub URLs', async () => {
190
- const fetcher = createMockFetcher({
191
- 'https://github.com/owner/repo': 'Content',
192
- });
193
- manager.registerFetcher('github', fetcher);
194
-
195
- const entry = await manager.getWithFallback('github-key', 'https://github.com/owner/repo');
196
- expect(entry.metadata.source).toBe('github');
197
- });
198
-
199
- it('should detect Confluence URLs', async () => {
200
- const fetcher = createMockFetcher({
201
- 'https://mycompany.atlassian.net/wiki/page': 'Content',
202
- });
203
- manager.registerFetcher('confluence', fetcher);
204
-
205
- const entry = await manager.getWithFallback(
206
- 'confluence-key',
207
- 'https://mycompany.atlassian.net/wiki/page'
208
- );
209
- expect(entry.metadata.source).toBe('confluence');
210
- });
211
-
212
- it('should detect Notion URLs', async () => {
213
- const fetcher = createMockFetcher({
214
- 'https://notion.so/page': 'Content',
215
- });
216
- manager.registerFetcher('notion', fetcher);
217
-
218
- const entry = await manager.getWithFallback('notion-key', 'https://notion.so/page');
219
- expect(entry.metadata.source).toBe('notion');
220
- });
221
- });
222
-
223
- describe('syncEntries', () => {
224
- beforeEach(async () => {
225
- const fetcher = createMockFetcher({
226
- 'https://github.com/test1': 'Content 1',
227
- 'https://github.com/test2': 'Content 2',
228
- });
229
- manager.registerFetcher('github', fetcher);
230
-
231
- // Pre-populate cache
232
- await manager.getWithFallback('key1', 'https://github.com/test1');
233
- await manager.getWithFallback('key2', 'https://github.com/test2');
234
- });
235
-
236
- it('should sync specified entries', async () => {
237
- const result = await manager.syncEntries(['key1', 'key2']);
238
-
239
- expect(result.updated).toBeGreaterThanOrEqual(0);
240
- expect(result.failed).toBe(0);
241
- expect(result.duration).toBeGreaterThanOrEqual(0);
242
- });
243
-
244
- it('should report errors for missing entries', async () => {
245
- const result = await manager.syncEntries(['missing-key'], { continueOnError: true });
246
-
247
- expect(result.failed).toBe(1);
248
- expect(result.errors[0].key).toBe('missing-key');
249
- });
250
- });
251
- });
252
-
253
- describe('createCacheManager', () => {
254
- it('should create a manager instance', async () => {
255
- const testDir = join(tmpdir(), `create-manager-${Date.now()}`);
256
- await fs.mkdir(testDir, { recursive: true });
257
-
258
- const cache = new FileCacheProvider({ basePath: testDir });
259
- await cache.initialize();
260
-
261
- const manager = createCacheManager({ cache });
262
- expect(manager).toBeInstanceOf(CacheManager);
263
-
264
- await fs.rm(testDir, { recursive: true, force: true });
265
- });
266
- });