@deimoscloud/coreai 0.1.9 → 0.1.11
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/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
- package/.prettierrc +0 -9
- package/AGENT_SPEC.md +0 -347
- package/ARCHITECTURE.md +0 -547
- package/DRAFT_PRD.md +0 -1440
- package/IMPLEMENTATION_PLAN.md +0 -256
- package/PRODUCT.md +0 -473
- package/WORKFLOWS.md +0 -295
- package/commands/core/check-inbox.md +0 -34
- package/commands/core/delegate.md +0 -30
- package/commands/core/git-commit.md +0 -144
- package/commands/core/pr-create.md +0 -193
- package/commands/core/review.md +0 -56
- package/commands/core/sprint-status.md +0 -65
- package/commands/optional/docs-update.md +0 -200
- package/commands/optional/jira-create.md +0 -200
- package/commands/optional/jira-transition.md +0 -184
- package/commands/optional/worktree-cleanup.md +0 -167
- package/commands/optional/worktree-setup.md +0 -110
- package/eslint.config.js +0 -29
- package/jest.config.js +0 -22
- package/knowledge-library/README.md +0 -118
- package/knowledge-library/android-engineer/context/current.txt +0 -42
- package/knowledge-library/android-engineer/control/decisions.txt +0 -9
- package/knowledge-library/android-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/android-engineer/control/objectives.txt +0 -26
- package/knowledge-library/android-engineer/history/.gitkeep +0 -0
- package/knowledge-library/android-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/android-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/android-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/architecture.txt +0 -61
- package/knowledge-library/backend-engineer/context/current.txt +0 -42
- package/knowledge-library/backend-engineer/control/decisions.txt +0 -9
- package/knowledge-library/backend-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/backend-engineer/control/objectives.txt +0 -26
- package/knowledge-library/backend-engineer/history/.gitkeep +0 -0
- package/knowledge-library/backend-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/backend-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/backend-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/context.txt +0 -52
- package/knowledge-library/devops-engineer/context/current.txt +0 -42
- package/knowledge-library/devops-engineer/control/decisions.txt +0 -9
- package/knowledge-library/devops-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/devops-engineer/control/objectives.txt +0 -26
- package/knowledge-library/devops-engineer/history/.gitkeep +0 -0
- package/knowledge-library/devops-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/devops-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/devops-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/context/current.txt +0 -40
- package/knowledge-library/engineering-manager/control/decisions.txt +0 -9
- package/knowledge-library/engineering-manager/control/objectives.txt +0 -27
- package/knowledge-library/engineering-manager/history/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/outbox/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/tech/.gitkeep +0 -0
- package/knowledge-library/prd.txt +0 -81
- package/knowledge-library/product-manager/context/current.txt +0 -42
- package/knowledge-library/product-manager/control/decisions.txt +0 -9
- package/knowledge-library/product-manager/control/dependencies.txt +0 -19
- package/knowledge-library/product-manager/control/objectives.txt +0 -26
- package/knowledge-library/product-manager/history/.gitkeep +0 -0
- package/knowledge-library/product-manager/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/product-manager/outbox/.gitkeep +0 -0
- package/knowledge-library/product-manager/tech/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/context/current.txt +0 -42
- package/knowledge-library/qa-engineer/control/decisions.txt +0 -9
- package/knowledge-library/qa-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/qa-engineer/control/objectives.txt +0 -26
- package/knowledge-library/qa-engineer/history/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/security-engineer/context/current.txt +0 -42
- package/knowledge-library/security-engineer/control/decisions.txt +0 -9
- package/knowledge-library/security-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/security-engineer/control/objectives.txt +0 -26
- package/knowledge-library/security-engineer/history/.gitkeep +0 -0
- package/knowledge-library/security-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/security-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/security-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/context/current.txt +0 -42
- package/knowledge-library/solutions-architect/control/decisions.txt +0 -9
- package/knowledge-library/solutions-architect/control/dependencies.txt +0 -19
- package/knowledge-library/solutions-architect/control/objectives.txt +0 -26
- package/knowledge-library/solutions-architect/history/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/outbox/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/tech/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/context/current.txt +0 -42
- package/knowledge-library/wearos-engineer/control/decisions.txt +0 -9
- package/knowledge-library/wearos-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/wearos-engineer/control/objectives.txt +0 -26
- package/knowledge-library/wearos-engineer/history/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/tech/.gitkeep +0 -0
- package/scripts/add-agent.sh +0 -323
- package/scripts/install.sh +0 -354
- package/src/adapters/factory.test.ts +0 -386
- package/src/adapters/factory.ts +0 -305
- package/src/adapters/index.ts +0 -113
- package/src/adapters/interfaces.ts +0 -268
- package/src/adapters/mcp/client.test.ts +0 -130
- package/src/adapters/mcp/client.ts +0 -451
- package/src/adapters/mcp/discovery.test.ts +0 -315
- package/src/adapters/mcp/discovery.ts +0 -340
- package/src/adapters/mcp/index.ts +0 -66
- package/src/adapters/mcp/mapper.test.ts +0 -218
- package/src/adapters/mcp/mapper.ts +0 -536
- package/src/adapters/mcp/registry.test.ts +0 -433
- package/src/adapters/mcp/registry.ts +0 -550
- package/src/adapters/mcp/types.ts +0 -258
- package/src/adapters/native/filesystem.test.ts +0 -350
- package/src/adapters/native/filesystem.ts +0 -393
- package/src/adapters/native/github.test.ts +0 -173
- package/src/adapters/native/github.ts +0 -627
- package/src/adapters/native/index.ts +0 -22
- package/src/adapters/native/selector.test.ts +0 -224
- package/src/adapters/native/selector.ts +0 -150
- package/src/adapters/types.ts +0 -270
- package/src/agents/compiler.test.ts +0 -410
- package/src/agents/compiler.ts +0 -424
- package/src/agents/index.ts +0 -37
- package/src/agents/loader.test.ts +0 -319
- package/src/agents/loader.ts +0 -143
- package/src/agents/resolver.test.ts +0 -282
- package/src/agents/resolver.ts +0 -262
- package/src/agents/types.ts +0 -97
- package/src/cache/index.ts +0 -38
- package/src/cache/interfaces.ts +0 -283
- package/src/cache/manager.test.ts +0 -266
- package/src/cache/manager.ts +0 -388
- package/src/cache/provider.test.ts +0 -485
- package/src/cache/provider.ts +0 -745
- package/src/cache/types.test.ts +0 -192
- package/src/cache/types.ts +0 -313
- package/src/cli/commands/build.test.ts +0 -248
- package/src/cli/commands/build.ts +0 -284
- package/src/cli/commands/cache.test.ts +0 -221
- package/src/cli/commands/cache.ts +0 -229
- package/src/cli/commands/index.ts +0 -63
- package/src/cli/commands/init.test.ts +0 -173
- package/src/cli/commands/init.ts +0 -296
- package/src/cli/commands/skills.test.ts +0 -272
- package/src/cli/commands/skills.ts +0 -348
- package/src/cli/commands/status.test.ts +0 -392
- package/src/cli/commands/status.ts +0 -332
- package/src/cli/commands/sync.test.ts +0 -213
- package/src/cli/commands/sync.ts +0 -251
- package/src/cli/commands/validate.test.ts +0 -216
- package/src/cli/commands/validate.ts +0 -340
- package/src/cli/index.test.ts +0 -190
- package/src/cli/index.ts +0 -493
- package/src/commands/context.test.ts +0 -163
- package/src/commands/context.ts +0 -111
- package/src/commands/index.ts +0 -56
- package/src/commands/loader.test.ts +0 -273
- package/src/commands/loader.ts +0 -355
- package/src/commands/registry.test.ts +0 -384
- package/src/commands/registry.ts +0 -248
- package/src/commands/runner.test.ts +0 -297
- package/src/commands/runner.ts +0 -222
- package/src/commands/types.ts +0 -361
- package/src/config/index.ts +0 -19
- package/src/config/loader.test.ts +0 -262
- package/src/config/loader.ts +0 -188
- package/src/config/types.ts +0 -154
- package/src/context/index.ts +0 -14
- package/src/context/loader.test.ts +0 -334
- package/src/context/loader.ts +0 -357
- package/src/index.test.ts +0 -13
- package/src/index.ts +0 -268
- package/src/knowledge-library/index.ts +0 -44
- package/src/knowledge-library/manager.test.ts +0 -536
- package/src/knowledge-library/manager.ts +0 -804
- package/src/knowledge-library/types.ts +0 -432
- package/src/skills/generator.test.ts +0 -602
- package/src/skills/generator.ts +0 -491
- package/src/skills/index.ts +0 -27
- package/src/skills/templates.ts +0 -520
- package/src/skills/types.ts +0 -251
- package/templates/completion-report.md +0 -72
- package/templates/feedback.md +0 -56
- package/templates/project-files/CLAUDE.md.template +0 -109
- package/templates/project-files/coreai.json.example +0 -47
- package/templates/project-files/mcp.json.template +0 -20
- package/templates/review-complete.md +0 -64
- package/templates/review-request.md +0 -67
- package/templates/task-assignment.md +0 -51
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -26
- package/tsup.config.ts +0 -23
package/src/cache/interfaces.ts
DELETED
|
@@ -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
|
-
});
|